CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_5/src/EventFilter/ResourceBroker/src/ResourceChecker.cc

Go to the documentation of this file.
00001 /*
00002  * ResourceChecker.cc
00003  *
00004  *  Created on: Nov 23, 2011
00005  *      Author: aspataru : aspataru@cern.ch
00006  */
00007 
00008 #include "EventFilter/ResourceBroker/interface/ResourceChecker.h"
00009 #include "EventFilter/Utilities/interface/GlobalEventNumber.h"
00010 #include "DataFormats/FEDRawData/interface/FEDNumbering.h"
00011 
00012 #include "interface/evb/i2oEVBMsgs.h"
00013 #include "interface/shared/frl_header.h"
00014 #include "interface/shared/fed_header.h"
00015 #include "interface/shared/fed_trailer.h"
00016 #include "EvffedFillerRB.h"
00017 
00018 #include <sstream>
00019 
00020 using namespace evf;
00021 using std::stringstream;
00022 using std::ostringstream;
00023 using std::hex;
00024 using std::dec;
00025 
00026 //______________________________________________________________________________
00027 ResourceChecker::ResourceChecker(FUResource* const resToCheck) :
00028         res_(resToCheck) {
00029 }
00030 
00031 //______________________________________________________________________________
00032 void ResourceChecker::processDataBlock(MemRef_t* bufRef) throw (evf::Exception) {
00033         // reset iBlock_/nBlock_ counters
00034         if (res_->iBlock_ == res_->nBlock_) {
00035                 res_->iBlock_ = 0;
00036                 res_->nBlock_ = 0xffffffff;
00037         }
00038 
00039         I2O_EVENT_DATA_BLOCK_MESSAGE_FRAME *block =
00040                         (I2O_EVENT_DATA_BLOCK_MESSAGE_FRAME*) bufRef->getDataLocation();
00041 
00042         UInt_t iBlock = block->blockNb;
00043         UInt_t nBlock = block->nbBlocksInSuperFragment;
00044         UInt_t iSuperFrag = block->superFragmentNb;
00045         UInt_t nSuperFrag = block->nbSuperFragmentsInEvent;
00046         UInt_t fuResourceId = block->fuTransactionId;
00047         UInt_t buResourceId = block->buResourceId;
00048         UInt_t evtNumber = block->eventNumber;
00049         stringstream oss;
00050         oss << "TransId:" << fuResourceId << " BUResourceId:" << buResourceId
00051                         << " eventNumber:" << evtNumber << " ";
00052         // check fuResourceId consistency
00053         if (fuResourceId != res_->fuResourceId_) {
00054                 res_->nbErrors_++;
00055 
00056                 oss << "RU/FU fuResourceId mismatch." << " Received:" << fuResourceId
00057                                 << " Expected:" << res_->fuResourceId_;
00058                 XCEPT_RAISE(evf::Exception, oss.str());
00059         }
00060 
00061         // check iBlock consistency
00062         if (iBlock != res_->iBlock_) {
00063                 res_->nbErrors_++;
00064                 oss << "RU/FU block number mismatch." << " Received:" << iBlock
00065                                 << " Expected:" << res_->iBlock_;
00066                 XCEPT_RAISE(evf::Exception, oss.str());
00067         }
00068 
00069         // check iSuperFrag consistency
00070         if (iSuperFrag != res_->iSuperFrag_) {
00071                 res_->nbErrors_++;
00072                 oss << "RU/FU superfragment number mismatch." << " Received:"
00073                                 << iSuperFrag << " Expected:" << res_->iSuperFrag_;
00074                 XCEPT_RAISE(evf::Exception, oss.str());
00075         }
00076 
00077         // assign nBlock_
00078         if (iBlock == 0) {
00079                 res_->nBlock_ = nBlock;
00080         } else {
00081                 // check nBlock_
00082                 if (nBlock != res_->nBlock_) {
00083                         res_->nbErrors_++;
00084                         oss << "RU/FU number of blocks mismatch." << " Received:" << nBlock
00085                                         << " Expected:" << res_->nBlock_;
00086                         XCEPT_RAISE(evf::Exception, oss.str());
00087                 }
00088         }
00089 
00090         // if this is the first block in the event,
00091         // *assign* evtNumber,buResourceId,nSuperFrag ...
00092         if (iBlock == 0 && iSuperFrag == 0) {
00093                 res_->evtNumber_ = evtNumber;
00094                 res_->buResourceId_ = buResourceId;
00095                 res_->nSuperFrag_ = nSuperFrag;
00096 
00097                 res_->shmCell_->setEvtNumber(evtNumber);
00098                 res_->shmCell_->setBuResourceId(buResourceId);
00099 
00100                 // check that buffers are allocated for nSuperFrag superfragments
00101                 if (res_->nSuperFrag_ > res_->nSuperFragMax_) {
00102                         res_->nbErrors_++;
00103                         oss << "Invalid maximum number of superfragments."
00104                                         << " fuResourceId:" << res_->fuResourceId_ << " evtNumber:"
00105                                         << res_->evtNumber_ << " nSuperFrag:" << res_->nSuperFrag_
00106                                         << " nSuperFragMax:" << res_->nSuperFragMax_;
00107                         XCEPT_RAISE(evf::Exception, oss.str());
00108                 }
00109         }
00110         // ... otherwise,
00111         // *check* evtNumber,buResourceId,nSuperFrag
00112         else {
00113                 // check evtNumber
00114                 if (evtNumber != res_->evtNumber_) {
00115                         res_->nbErrors_++;
00116                         oss << "RU/FU evtNumber mismatch." << " Received:" << evtNumber
00117                                         << " Expected:" << res_->evtNumber_;
00118                         XCEPT_RAISE(evf::Exception, oss.str());
00119                 }
00120 
00121                 // check buResourceId
00122                 if (buResourceId != res_->buResourceId_) {
00123                         res_->nbErrors_++;
00124                         oss << "RU/FU buResourceId mismatch."// implemented in subclasses (for now) << " Received:"
00125                                         << buResourceId << " Expected:" << res_->buResourceId_;
00126                         XCEPT_RAISE(evf::Exception, oss.str());
00127                 }
00128 
00129                 // check nSuperFrag
00130                 if (nSuperFrag != res_->nSuperFrag_) {
00131                         res_->nbErrors_++;
00132                         oss << "RU/FU number of superfragments mismatch." << " Received:"
00133                                         << nSuperFrag << " Expected:" << res_->nSuperFrag_;
00134                         XCEPT_RAISE(evf::Exception, oss.str());
00135                 }
00136         }
00137 
00138         // check payload
00139         try {
00140                 checkDataBlockPayload(bufRef);
00141         } catch (xcept::Exception& e) {
00142                 oss << "data block payload failed check." << " evtNumber:"
00143                                 << res_->evtNumber_ << " buResourceId:" << res_->buResourceId_
00144                                 << " iSuperFrag:" << res_->iSuperFrag_;
00145                 XCEPT_RETHROW(evf::Exception, oss.str(), e);
00146         }
00147 
00148         res_->appendBlockToSuperFrag(bufRef);
00149 
00150         // increment iBlock_, as expected for the next message
00151         res_->iBlock_++;
00152 
00153         // superfragment complete ...
00154         bool lastBlockInSuperFrag = (iBlock == nBlock - 1);
00155         if (lastBlockInSuperFrag) {
00156 
00157                 // ... fill the FED buffers contained in the superfragment
00158                 try {
00159                         // UPDATED
00160                         res_->superFragSize(); // if event exceeds size an exception is thrown here, keep it distinct from SF corruption
00161                 } catch (xcept::Exception& e) {
00162                         oss << "Invalid super fragment size." << " evtNumber:"
00163                                         << res_->evtNumber_ << " buResourceId:"
00164                                         << res_->buResourceId_ << " iSuperFrag:"
00165                                         << res_->iSuperFrag_;
00166                         res_->removeLastAppendedBlockFromSuperFrag();
00167                         XCEPT_RETHROW(evf::Exception, oss.str(), e);
00168                 }
00169                 try {
00170                         res_->fillSuperFragPayload();
00171                         findFEDs();
00172 
00173                 } catch (xcept::Exception& e) {
00174                         oss << "Invalid super fragment." << " evtNumber:"
00175                                         << res_->evtNumber_ << " buResourceId:"
00176                                         << res_->buResourceId_ << " iSuperFrag:"
00177                                         << res_->iSuperFrag_;
00178                         res_->removeLastAppendedBlockFromSuperFrag();
00179                         XCEPT_RETHROW(evf::Exception, oss.str(), e);
00180                 }
00181 
00182                 // ... release the buffers associated with the superfragment
00183                 try {
00184                         res_->releaseSuperFrag();
00185                 } catch (xcept::Exception& e) {
00186                         res_->nbErrors_++;
00187                         oss << "Failed to release super fragment." << " evtNumber:"
00188                                         << res_->evtNumber_ << " buResourceId:"
00189                                         << res_->buResourceId_ << " iSuperFrag:"
00190                                         << res_->iSuperFrag_;
00191                         XCEPT_RETHROW(evf::Exception, oss.str(), e);
00192                 }
00193 
00194                 // increment iSuperFrag_, as expected for the next message(s)
00195                 res_->iSuperFrag_++;
00196 
00197         } // lastBlockInSuperFragment
00198 
00199         return;
00200 }
00201 
00202 //______________________________________________________________________________
00203 void ResourceChecker::checkDataBlockPayload(MemRef_t* bufRef)
00204                 throw (evf::Exception) {
00205         UInt_t frameSize = 0;
00206         UInt_t bufSize = 0;
00207         UInt_t segSize = 0;
00208         UInt_t segSizeExpected = 0;
00209 
00210         frlh_t *frlHeader = 0;
00211 
00212         UChar_t *blockAddr = 0;
00213         UChar_t *frlHeaderAddr = 0;
00214 
00215         frameSize = sizeof(I2O_EVENT_DATA_BLOCK_MESSAGE_FRAME);
00216 
00217         blockAddr = (UChar_t*) bufRef->getDataLocation();
00218         frlHeaderAddr = blockAddr + frameSize;
00219         frlHeader = (frlh_t*) frlHeaderAddr;
00220 
00221         I2O_EVENT_DATA_BLOCK_MESSAGE_FRAME *block =
00222                         (I2O_EVENT_DATA_BLOCK_MESSAGE_FRAME*) blockAddr;
00223 
00224         // check that FRL trigno is consistent with FU evtNumber
00225         if (res_->evtNumber_ != frlHeader->trigno) {
00226                 res_->nbErrors_++;
00227                 stringstream oss;
00228                 oss << "FRL header \"trigno\" does not match " << "FU  \"evtNumber\"."
00229                                 << " trigno:" << frlHeader->trigno << " evtNumber:"
00230                                 << res_->evtNumber_;
00231                 XCEPT_RAISE(evf::Exception, oss.str());
00232         }
00233 
00234         // check that FRL trigno is consistent with RU eventNumber
00235         if (block->eventNumber != frlHeader->trigno) {
00236                 res_->nbErrors_++;
00237                 stringstream oss;
00238                 oss << "FRL header \"trigno\" does not match "
00239                                 << "RU builder header \"eventNumber\"." << " trigno:"
00240                                 << frlHeader->trigno << " eventNumber:" << block->eventNumber;
00241                 XCEPT_RAISE(evf::Exception, oss.str());
00242         }
00243 
00244         // check that block numbers reported by FRL / RU are consistent
00245         if (block->blockNb != frlHeader->segno) {
00246                 res_->nbErrors_++;
00247                 stringstream oss;
00248                 oss << "FRL header \"segno\" does not match"
00249                                 << "RU builder header \"blockNb\"." << " segno:"
00250                                 << frlHeader->segno << " blockNb:" << block->blockNb;
00251                 XCEPT_RAISE(evf::Exception, oss.str());
00252         }
00253 
00254         // reported block number consistent with expectation
00255         if (block->blockNb != res_->iBlock_) {
00256                 res_->nbErrors_++;
00257                 stringstream oss;
00258                 oss << "Incorrect block number." << " Expected:" << res_->iBlock_
00259                                 << " Received:" << block->blockNb;
00260                 XCEPT_RAISE(evf::Exception, oss.str());
00261         }
00262 
00263         // reported payload size consistent with expectation
00264         bufSize = bufRef->getDataSize();
00265         segSizeExpected = bufSize - frameSize - sizeof(frlh_t);
00266         segSize = frlHeader->segsize & FRL_SEGSIZE_MASK;
00267         if (segSize != segSizeExpected) {
00268                 res_->nbErrors_++;
00269                 stringstream oss;
00270                 oss << "FRL header segment size is not as expected." << " Expected:"
00271                                 << segSizeExpected << " Received:" << segSize;
00272                 XCEPT_RAISE(evf::Exception, oss.str());
00273         }
00274 
00275         // Check that FU and FRL headers agree on end of super-fragment
00276         bool fuLastBlockInSuperFrag = (block->blockNb
00277                         == (block->nbBlocksInSuperFragment - 1));
00278         bool frlLastBlockInSuperFrag = ((frlHeader->segsize & FRL_LAST_SEGM) != 0);
00279         if (fuLastBlockInSuperFrag != frlLastBlockInSuperFrag) {
00280                 res_->nbErrors_++;
00281                 stringstream oss;
00282                 oss << "FU / FRL header end-of-superfragment mismatch."
00283                                 << " FU header:" << fuLastBlockInSuperFrag << " FRL header:"
00284                                 << frlLastBlockInSuperFrag;
00285                 XCEPT_RAISE(evf::Exception, oss.str());
00286         }
00287 
00288         return;
00289 }
00290 
00291 //______________________________________________________________________________
00292 void ResourceChecker::findFEDs() throw (evf::Exception) {
00293         UChar_t* superFragAddr = 0;
00294         UInt_t superFragSize = 0;
00295 
00296         UChar_t *fedTrailerAddr = 0;
00297         UChar_t *fedHeaderAddr = 0;
00298 
00299         UInt_t fedSize = 0;
00300         UInt_t sumOfFedSizes = 0;
00301         UInt_t evtNumber = 0;
00302 
00303         UShort_t crc = 0;
00304         UShort_t crcChk = 0;
00305 
00306         fedt_t *fedTrailer = 0;
00307         fedh_t *fedHeader = 0;
00308 
00309         superFragAddr = res_->shmCell_->superFragAddr(res_->iSuperFrag_);
00310         superFragSize = res_->shmCell_->superFragSize(res_->iSuperFrag_);
00311         fedTrailerAddr = superFragAddr + superFragSize - sizeof(fedt_t);
00312 
00313         while (fedTrailerAddr > superFragAddr) {
00314 
00315                 fedTrailer = (fedt_t*) fedTrailerAddr;
00316                 fedSize = (fedTrailer->eventsize & FED_EVSZ_MASK) << 3;
00317                 sumOfFedSizes += fedSize;
00318 
00319                 // check for fed trailer id
00320                 if ((fedTrailer->eventsize & FED_TCTRLID_MASK) != FED_TCTRLID) {
00321                         res_->nbErrors_++;
00322                         stringstream oss;
00323                         oss << "Missing FED trailer id." << " evtNumber:"
00324                                         << res_->evtNumber_ << " iSuperFrag:" << res_->iSuperFrag_;
00325                         XCEPT_RAISE(evf::Exception, oss.str());
00326                 }
00327 
00328                 fedHeaderAddr = fedTrailerAddr - fedSize + sizeof(fedt_t);
00329 
00330                 // check that fed header is within buffer
00331                 if (fedHeaderAddr < superFragAddr) {
00332                         res_->nbErrors_++;
00333                         stringstream oss;
00334                         oss << "FED header address out-of-bounds." << " evtNumber:"
00335                                         << res_->evtNumber_ << " iSuperFrag:" << res_->iSuperFrag_;
00336                         XCEPT_RAISE(evf::Exception, oss.str());
00337                 }
00338 
00339                 // check that payload starts within buffer
00340                 if ((fedHeaderAddr + sizeof(fedh_t)) > (superFragAddr + superFragSize)) {
00341                         res_->nbErrors_++;
00342                         stringstream oss;
00343                         oss << "FED payload out-of-bounds." << " evtNumber:"
00344                                         << res_->evtNumber_ << " iSuperFrag:" << res_->iSuperFrag_;
00345                         XCEPT_RAISE(evf::Exception, oss.str());
00346                 }
00347 
00348                 fedHeader = (fedh_t*) fedHeaderAddr;
00349 
00350                 // check for fed header id
00351                 if ((fedHeader->eventid & FED_HCTRLID_MASK) != FED_HCTRLID) {
00352                         res_->nbErrors_++;
00353                         stringstream oss;
00354                         oss << "Missing FED header id." << " evtNumber:"
00355                                         << res_->evtNumber_ << " iSuperFrag:" << res_->iSuperFrag_;
00356                         XCEPT_RAISE(evf::Exception, oss.str());
00357                 }
00358 
00359                 UInt_t fedId = (fedHeader->sourceid & REAL_SOID_MASK) >> 8;
00360 
00361                 // check evtNumber consisency
00362                 evtNumber = fedHeader->eventid & FED_LVL1_MASK;
00363                 if (evtNumber != res_->evtNumber_) {
00364                         res_->nbErrors_++;
00365                         stringstream oss;
00366                         oss << "FU / FED evtNumber mismatch." << " FU:" << res_->evtNumber_
00367                                         << " FED:" << evtNumber << " fedid:" << fedId;
00368                         XCEPT_RAISE(evf::Exception, oss.str());
00369                 }
00370 
00371                 // check that fedid is within valid ranges
00372                 if (fedId >= 1024 || (res_->doFedIdCheck_ && (!FEDNumbering::inRange(
00373                                 fedId)))) {
00374                         LOG4CPLUS_WARN(
00375                                         res_->log_,
00376                                         "Invalid fedid. Data will still be logged" << " evtNumber:"
00377                                                         << res_->evtNumber_ << " fedid:" << fedId);
00378                         res_->nbErrors_++;
00379                 }
00380 
00381                 // check if a previous fed has already claimed same fed id
00382 
00383                 if (res_->fedSize_[fedId] != 0) {
00384                         LOG4CPLUS_ERROR(
00385                                         res_->log_,
00386                                         "Duplicated fedid. Data will be lost for" << " evtNumber:"
00387                                                         << res_->evtNumber_ << " fedid:" << fedId);
00388                         res_->nbErrors_++;
00389                 }
00390 
00391                 if (fedId < 1024)
00392                         res_->fedSize_[fedId] = fedSize;
00393 
00394                 //if gtp EVM block is available set cell event number to global partition-independent trigger number
00395                 //daq block partition-independent event number is left as an option in case of problems
00396 
00397                 if (fedId == res_->gtpeId_)
00398                         if (evf::evtn::gtpe_board_sense(fedHeaderAddr))
00399                                 res_->shmCell_->setEvtNumber(evf::evtn::gtpe_get(fedHeaderAddr));
00400                 if (res_->useEvmBoard_ && (fedId == res_->gtpEvmId_))
00401                         // UPDATED
00402                         if (evf::evtn::evm_board_sense(fedHeaderAddr, fedSize)) {
00403                                 res_->shmCell_->setEvtNumber(
00404                                                 evf::evtn::get(fedHeaderAddr, true));
00405                                 res_->shmCell_->setLumiSection(evf::evtn::getlbn(fedHeaderAddr));
00406                         }
00407                 if (!res_->useEvmBoard_ && (fedId == res_->gtpDaqId_))
00408 
00409                         if (evf::evtn::daq_board_sense(fedHeaderAddr)) {
00410                                 res_->shmCell_->setEvtNumber(
00411                                                 evf::evtn::get(fedHeaderAddr, false));
00412                         }
00413                 // crc check
00414                 if (res_->doCrcCheck_) {
00415                         UInt_t conscheck = fedTrailer->conscheck;
00416                         crc = ((fedTrailer->conscheck & FED_CRCS_MASK) >> FED_CRCS_SHIFT);
00417                         fedTrailer->conscheck &= (~FED_CRCS_MASK);
00418                         fedTrailer->conscheck &= (~FED_RBIT_MASK);
00419                         crcChk = compute_crc(fedHeaderAddr, fedSize);
00420                         if (res_->nextEventWillHaveCRCError_ && random() > RAND_MAX / 2) {
00421                                 crc--;
00422                                 res_->nextEventWillHaveCRCError_ = false;
00423                         }
00424                         if (crc != crcChk) {
00425                                 ostringstream oss;
00426                                 oss << "crc check failed." << " evtNumber:" << res_->evtNumber_
00427                                                 << " fedid:" << fedId << " crc:" << crc << " chk:"
00428                                                 << crcChk;
00429                                 LOG4CPLUS_INFO(res_->log_, oss.str());
00430                                 XCEPT_DECLARE(evf::Exception, sentinelException, oss.str());
00431                                 res_->app_->notifyQualified("error", sentinelException);
00432                                 res_->nbErrors_++;
00433                                 res_->nbCrcErrors_++;
00434                         }
00435                         fedTrailer->conscheck = conscheck;
00436                 }
00437 
00438                 // mark fed
00439                 if (!res_->shmCell_->markFed(fedId, fedSize, fedHeaderAddr)) {
00440                         res_->nbErrors_++;
00441                         stringstream oss;
00442                         oss << "Failed to mark fed in buffer." << " evtNumber:"
00443                                         << res_->evtNumber_ << " fedId:" << fedId << " fedSize:"
00444                                         << fedSize << " fedAddr:0x" << hex
00445                                         << (unsigned long) fedHeaderAddr << dec;
00446                         XCEPT_RAISE(evf::Exception, oss.str());
00447                 }
00448 
00449                 // Move to the next fed trailer
00450                 fedTrailerAddr = fedTrailerAddr - fedSize;
00451         }
00452 
00453         // check that we indeed end up on the starting address of the buffer
00454         if ((fedTrailerAddr + sizeof(fedh_t)) != superFragAddr) {
00455                 stringstream oss;
00456                 oss << "First FED in superfragment ouf-of-bound." << " evtNumber:"
00457                                 << res_->evtNumber_ << " iSuperFrag:" << res_->iSuperFrag_;
00458                 XCEPT_RAISE(evf::Exception, oss.str());
00459         }
00460 
00461         return;
00462 }