CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
ResourceChecker.cc
Go to the documentation of this file.
1 /*
2  * ResourceChecker.cc
3  *
4  * Created on: Nov 23, 2011
5  * Author: aspataru : aspataru@cern.ch
6  */
7 
11 
12 #include "interface/evb/i2oEVBMsgs.h"
13 #include "interface/shared/frl_header.h"
14 #include "interface/shared/fed_header.h"
15 #include "interface/shared/fed_trailer.h"
16 #include "EvffedFillerRB.h"
17 
18 #include <sstream>
19 
20 using namespace evf;
21 using std::stringstream;
22 using std::ostringstream;
23 using std::hex;
24 using std::dec;
25 
26 //______________________________________________________________________________
28  res_(resToCheck) {
29 }
30 
31 //______________________________________________________________________________
33  // reset iBlock_/nBlock_ counters
34  if (res_->iBlock_ == res_->nBlock_) {
35  res_->iBlock_ = 0;
36  res_->nBlock_ = 0xffffffff;
37  }
38 
39  I2O_EVENT_DATA_BLOCK_MESSAGE_FRAME *block =
40  (I2O_EVENT_DATA_BLOCK_MESSAGE_FRAME*) bufRef->getDataLocation();
41 
42  UInt_t iBlock = block->blockNb;
43  UInt_t nBlock = block->nbBlocksInSuperFragment;
44  UInt_t iSuperFrag = block->superFragmentNb;
45  UInt_t nSuperFrag = block->nbSuperFragmentsInEvent;
46  UInt_t fuResourceId = block->fuTransactionId;
47  UInt_t buResourceId = block->buResourceId;
48  UInt_t evtNumber = block->eventNumber;
49  stringstream oss;
50  oss << "TransId:" << fuResourceId << " BUResourceId:" << buResourceId
51  << " eventNumber:" << evtNumber << " ";
52  // check fuResourceId consistency
53  if (fuResourceId != res_->fuResourceId_) {
54  res_->nbErrors_++;
55 
56  oss << "RU/FU fuResourceId mismatch." << " Received:" << fuResourceId
57  << " Expected:" << res_->fuResourceId_;
58  XCEPT_RAISE(evf::Exception, oss.str());
59  }
60 
61  // check iBlock consistency
62  if (iBlock != res_->iBlock_) {
63  res_->nbErrors_++;
64  oss << "RU/FU block number mismatch." << " Received:" << iBlock
65  << " Expected:" << res_->iBlock_;
66  XCEPT_RAISE(evf::Exception, oss.str());
67  }
68 
69  // check iSuperFrag consistency
70  if (iSuperFrag != res_->iSuperFrag_) {
71  res_->nbErrors_++;
72  oss << "RU/FU superfragment number mismatch." << " Received:"
73  << iSuperFrag << " Expected:" << res_->iSuperFrag_;
74  XCEPT_RAISE(evf::Exception, oss.str());
75  }
76 
77  // assign nBlock_
78  if (iBlock == 0) {
79  res_->nBlock_ = nBlock;
80  } else {
81  // check nBlock_
82  if (nBlock != res_->nBlock_) {
83  res_->nbErrors_++;
84  oss << "RU/FU number of blocks mismatch." << " Received:" << nBlock
85  << " Expected:" << res_->nBlock_;
86  XCEPT_RAISE(evf::Exception, oss.str());
87  }
88  }
89 
90  // if this is the first block in the event,
91  // *assign* evtNumber,buResourceId,nSuperFrag ...
92  if (iBlock == 0 && iSuperFrag == 0) {
93  res_->evtNumber_ = evtNumber;
94  res_->buResourceId_ = buResourceId;
95  res_->nSuperFrag_ = nSuperFrag;
96 
97  res_->shmCell_->setEvtNumber(evtNumber);
98  res_->shmCell_->setBuResourceId(buResourceId);
99 
100  // check that buffers are allocated for nSuperFrag superfragments
101  if (res_->nSuperFrag_ > res_->nSuperFragMax_) {
102  res_->nbErrors_++;
103  oss << "Invalid maximum number of superfragments."
104  << " fuResourceId:" << res_->fuResourceId_ << " evtNumber:"
105  << res_->evtNumber_ << " nSuperFrag:" << res_->nSuperFrag_
106  << " nSuperFragMax:" << res_->nSuperFragMax_;
107  XCEPT_RAISE(evf::Exception, oss.str());
108  }
109  }
110  // ... otherwise,
111  // *check* evtNumber,buResourceId,nSuperFrag
112  else {
113  // check evtNumber
114  if (evtNumber != res_->evtNumber_) {
115  res_->nbErrors_++;
116  oss << "RU/FU evtNumber mismatch." << " Received:" << evtNumber
117  << " Expected:" << res_->evtNumber_;
118  XCEPT_RAISE(evf::Exception, oss.str());
119  }
120 
121  // check buResourceId
122  if (buResourceId != res_->buResourceId_) {
123  res_->nbErrors_++;
124  oss << "RU/FU buResourceId mismatch."// implemented in subclasses (for now) << " Received:"
125  << buResourceId << " Expected:" << res_->buResourceId_;
126  XCEPT_RAISE(evf::Exception, oss.str());
127  }
128 
129  // check nSuperFrag
130  if (nSuperFrag != res_->nSuperFrag_) {
131  res_->nbErrors_++;
132  oss << "RU/FU number of superfragments mismatch." << " Received:"
133  << nSuperFrag << " Expected:" << res_->nSuperFrag_;
134  XCEPT_RAISE(evf::Exception, oss.str());
135  }
136  }
137 
138  // check payload
139  try {
140  checkDataBlockPayload(bufRef);
141  } catch (xcept::Exception& e) {
142  oss << "data block payload failed check." << " evtNumber:"
143  << res_->evtNumber_ << " buResourceId:" << res_->buResourceId_
144  << " iSuperFrag:" << res_->iSuperFrag_;
145  XCEPT_RETHROW(evf::Exception, oss.str(), e);
146  }
147 
148  res_->appendBlockToSuperFrag(bufRef);
149 
150  // increment iBlock_, as expected for the next message
151  res_->iBlock_++;
152 
153  // superfragment complete ...
154  bool lastBlockInSuperFrag = (iBlock == nBlock - 1);
155  if (lastBlockInSuperFrag) {
156 
157  // ... fill the FED buffers contained in the superfragment
158  try {
159  // UPDATED
160  res_->superFragSize(); // if event exceeds size an exception is thrown here, keep it distinct from SF corruption
161  } catch (xcept::Exception& e) {
162  oss << "Invalid super fragment size." << " evtNumber:"
163  << res_->evtNumber_ << " buResourceId:"
164  << res_->buResourceId_ << " iSuperFrag:"
165  << res_->iSuperFrag_;
166  res_->removeLastAppendedBlockFromSuperFrag();
167  XCEPT_RETHROW(evf::Exception, oss.str(), e);
168  }
169  try {
170  res_->fillSuperFragPayload();
171  findFEDs();
172 
173  } catch (xcept::Exception& e) {
174  oss << "Invalid super fragment." << " evtNumber:"
175  << res_->evtNumber_ << " buResourceId:"
176  << res_->buResourceId_ << " iSuperFrag:"
177  << res_->iSuperFrag_;
178  res_->removeLastAppendedBlockFromSuperFrag();
179  XCEPT_RETHROW(evf::Exception, oss.str(), e);
180  }
181 
182  // ... release the buffers associated with the superfragment
183  try {
184  res_->releaseSuperFrag();
185  } catch (xcept::Exception& e) {
186  res_->nbErrors_++;
187  oss << "Failed to release super fragment." << " evtNumber:"
188  << res_->evtNumber_ << " buResourceId:"
189  << res_->buResourceId_ << " iSuperFrag:"
190  << res_->iSuperFrag_;
191  XCEPT_RETHROW(evf::Exception, oss.str(), e);
192  }
193 
194  // increment iSuperFrag_, as expected for the next message(s)
195  res_->iSuperFrag_++;
196 
197  } // lastBlockInSuperFragment
198 
199  return;
200 }
201 
202 //______________________________________________________________________________
204  throw (evf::Exception) {
205  UInt_t frameSize = 0;
206  UInt_t bufSize = 0;
207  UInt_t segSize = 0;
208  UInt_t segSizeExpected = 0;
209 
210  frlh_t *frlHeader = 0;
211 
212  UChar_t *blockAddr = 0;
213  UChar_t *frlHeaderAddr = 0;
214 
215  frameSize = sizeof(I2O_EVENT_DATA_BLOCK_MESSAGE_FRAME);
216 
217  blockAddr = (UChar_t*) bufRef->getDataLocation();
218  frlHeaderAddr = blockAddr + frameSize;
219  frlHeader = (frlh_t*) frlHeaderAddr;
220 
221  I2O_EVENT_DATA_BLOCK_MESSAGE_FRAME *block =
222  (I2O_EVENT_DATA_BLOCK_MESSAGE_FRAME*) blockAddr;
223 
224  // check that FRL trigno is consistent with FU evtNumber
225  if (res_->evtNumber_ != frlHeader->trigno) {
226  res_->nbErrors_++;
227  stringstream oss;
228  oss << "FRL header \"trigno\" does not match " << "FU \"evtNumber\"."
229  << " trigno:" << frlHeader->trigno << " evtNumber:"
230  << res_->evtNumber_;
231  XCEPT_RAISE(evf::Exception, oss.str());
232  }
233 
234  // check that FRL trigno is consistent with RU eventNumber
235  if (block->eventNumber != frlHeader->trigno) {
236  res_->nbErrors_++;
237  stringstream oss;
238  oss << "FRL header \"trigno\" does not match "
239  << "RU builder header \"eventNumber\"." << " trigno:"
240  << frlHeader->trigno << " eventNumber:" << block->eventNumber;
241  XCEPT_RAISE(evf::Exception, oss.str());
242  }
243 
244  // check that block numbers reported by FRL / RU are consistent
245  if (block->blockNb != frlHeader->segno) {
246  res_->nbErrors_++;
247  stringstream oss;
248  oss << "FRL header \"segno\" does not match"
249  << "RU builder header \"blockNb\"." << " segno:"
250  << frlHeader->segno << " blockNb:" << block->blockNb;
251  XCEPT_RAISE(evf::Exception, oss.str());
252  }
253 
254  // reported block number consistent with expectation
255  if (block->blockNb != res_->iBlock_) {
256  res_->nbErrors_++;
257  stringstream oss;
258  oss << "Incorrect block number." << " Expected:" << res_->iBlock_
259  << " Received:" << block->blockNb;
260  XCEPT_RAISE(evf::Exception, oss.str());
261  }
262 
263  // reported payload size consistent with expectation
264  bufSize = bufRef->getDataSize();
265  segSizeExpected = bufSize - frameSize - sizeof(frlh_t);
266  segSize = frlHeader->segsize & FRL_SEGSIZE_MASK;
267  if (segSize != segSizeExpected) {
268  res_->nbErrors_++;
269  stringstream oss;
270  oss << "FRL header segment size is not as expected." << " Expected:"
271  << segSizeExpected << " Received:" << segSize;
272  XCEPT_RAISE(evf::Exception, oss.str());
273  }
274 
275  // Check that FU and FRL headers agree on end of super-fragment
276  bool fuLastBlockInSuperFrag = (block->blockNb
277  == (block->nbBlocksInSuperFragment - 1));
278  bool frlLastBlockInSuperFrag = ((frlHeader->segsize & FRL_LAST_SEGM) != 0);
279  if (fuLastBlockInSuperFrag != frlLastBlockInSuperFrag) {
280  res_->nbErrors_++;
281  stringstream oss;
282  oss << "FU / FRL header end-of-superfragment mismatch."
283  << " FU header:" << fuLastBlockInSuperFrag << " FRL header:"
284  << frlLastBlockInSuperFrag;
285  XCEPT_RAISE(evf::Exception, oss.str());
286  }
287 
288  return;
289 }
290 
291 //______________________________________________________________________________
293  UChar_t* superFragAddr = 0;
294  UInt_t superFragSize = 0;
295 
296  UChar_t *fedTrailerAddr = 0;
297  UChar_t *fedHeaderAddr = 0;
298 
299  UInt_t fedSize = 0;
300  UInt_t sumOfFedSizes = 0;
301  UInt_t evtNumber = 0;
302 
303  UShort_t crc = 0;
304  UShort_t crcChk = 0;
305 
306  fedt_t *fedTrailer = 0;
307  fedh_t *fedHeader = 0;
308 
309  superFragAddr = res_->shmCell_->superFragAddr(res_->iSuperFrag_);
310  superFragSize = res_->shmCell_->superFragSize(res_->iSuperFrag_);
311  fedTrailerAddr = superFragAddr + superFragSize - sizeof(fedt_t);
312 
313  while (fedTrailerAddr > superFragAddr) {
314 
315  fedTrailer = (fedt_t*) fedTrailerAddr;
316  fedSize = (fedTrailer->eventsize & FED_EVSZ_MASK) << 3;
317  sumOfFedSizes += fedSize;
318 
319  // check for fed trailer id
320  if ((fedTrailer->eventsize & FED_TCTRLID_MASK) != FED_TCTRLID) {
321  res_->nbErrors_++;
322  stringstream oss;
323  oss << "Missing FED trailer id." << " evtNumber:"
324  << res_->evtNumber_ << " iSuperFrag:" << res_->iSuperFrag_;
325  XCEPT_RAISE(evf::Exception, oss.str());
326  }
327 
328  fedHeaderAddr = fedTrailerAddr - fedSize + sizeof(fedt_t);
329 
330  // check that fed header is within buffer
331  if (fedHeaderAddr < superFragAddr) {
332  res_->nbErrors_++;
333  stringstream oss;
334  oss << "FED header address out-of-bounds." << " evtNumber:"
335  << res_->evtNumber_ << " iSuperFrag:" << res_->iSuperFrag_;
336  XCEPT_RAISE(evf::Exception, oss.str());
337  }
338 
339  // check that payload starts within buffer
340  if ((fedHeaderAddr + sizeof(fedh_t)) > (superFragAddr + superFragSize)) {
341  res_->nbErrors_++;
342  stringstream oss;
343  oss << "FED payload out-of-bounds." << " evtNumber:"
344  << res_->evtNumber_ << " iSuperFrag:" << res_->iSuperFrag_;
345  XCEPT_RAISE(evf::Exception, oss.str());
346  }
347 
348  fedHeader = (fedh_t*) fedHeaderAddr;
349 
350  // check for fed header id
351  if ((fedHeader->eventid & FED_HCTRLID_MASK) != FED_HCTRLID) {
352  res_->nbErrors_++;
353  stringstream oss;
354  oss << "Missing FED header id." << " evtNumber:"
355  << res_->evtNumber_ << " iSuperFrag:" << res_->iSuperFrag_;
356  XCEPT_RAISE(evf::Exception, oss.str());
357  }
358 
359  UInt_t fedId = (fedHeader->sourceid & REAL_SOID_MASK) >> 8;
360 
361  // check evtNumber consisency
362  evtNumber = fedHeader->eventid & FED_LVL1_MASK;
363  if (evtNumber != res_->evtNumber_) {
364  res_->nbErrors_++;
365  stringstream oss;
366  oss << "FU / FED evtNumber mismatch." << " FU:" << res_->evtNumber_
367  << " FED:" << evtNumber << " fedid:" << fedId;
368  XCEPT_RAISE(evf::Exception, oss.str());
369  }
370 
371  // check that fedid is within valid ranges
372  if (fedId >= 1024 || (res_->doFedIdCheck_ && (!FEDNumbering::inRange(
373  fedId)))) {
374  LOG4CPLUS_WARN(
375  res_->log_,
376  "Invalid fedid. Data will still be logged" << " evtNumber:"
377  << res_->evtNumber_ << " fedid:" << fedId);
378  res_->nbErrors_++;
379  }
380 
381  // check if a previous fed has already claimed same fed id
382 
383  if (res_->fedSize_[fedId] != 0) {
384  LOG4CPLUS_ERROR(
385  res_->log_,
386  "Duplicated fedid. Data will be lost for" << " evtNumber:"
387  << res_->evtNumber_ << " fedid:" << fedId);
388  res_->nbErrors_++;
389  }
390 
391  if (fedId < 1024)
392  res_->fedSize_[fedId] = fedSize;
393 
394  //if gtp EVM block is available set cell event number to global partition-independent trigger number
395  //daq block partition-independent event number is left as an option in case of problems
396 
397  if (fedId == res_->gtpeId_)
398  if (evf::evtn::gtpe_board_sense(fedHeaderAddr))
399  res_->shmCell_->setEvtNumber(evf::evtn::gtpe_get(fedHeaderAddr));
400  if (res_->useEvmBoard_ && (fedId == res_->gtpEvmId_))
401  // UPDATED
402  if (evf::evtn::evm_board_sense(fedHeaderAddr, fedSize)) {
404  evf::evtn::get(fedHeaderAddr, true));
405  res_->shmCell_->setLumiSection(evf::evtn::getlbn(fedHeaderAddr));
406  }
407  if (!res_->useEvmBoard_ && (fedId == res_->gtpDaqId_))
408 
409  if (evf::evtn::daq_board_sense(fedHeaderAddr)) {
411  evf::evtn::get(fedHeaderAddr, false));
412  }
413  // crc check
414  if (res_->doCrcCheck_) {
415  UInt_t conscheck = fedTrailer->conscheck;
416  crc = ((fedTrailer->conscheck & FED_CRCS_MASK) >> FED_CRCS_SHIFT);
417  fedTrailer->conscheck &= (~FED_CRCS_MASK);
418  fedTrailer->conscheck &= (~FED_RBIT_MASK);
419  crcChk = compute_crc(fedHeaderAddr, fedSize);
420  if (res_->nextEventWillHaveCRCError_ && random() > RAND_MAX / 2) {
421  crc--;
423  }
424  if (crc != crcChk) {
425  ostringstream oss;
426  oss << "crc check failed." << " evtNumber:" << res_->evtNumber_
427  << " fedid:" << fedId << " crc:" << crc << " chk:"
428  << crcChk;
429  LOG4CPLUS_INFO(res_->log_, oss.str());
430  XCEPT_DECLARE(evf::Exception, sentinelException, oss.str());
431  res_->app_->notifyQualified("error", sentinelException);
432  res_->nbErrors_++;
433  res_->nbCrcErrors_++;
434  }
435  fedTrailer->conscheck = conscheck;
436  }
437 
438  // mark fed
439  if (!res_->shmCell_->markFed(fedId, fedSize, fedHeaderAddr)) {
440  res_->nbErrors_++;
441  stringstream oss;
442  oss << "Failed to mark fed in buffer." << " evtNumber:"
443  << res_->evtNumber_ << " fedId:" << fedId << " fedSize:"
444  << fedSize << " fedAddr:0x" << hex
445  << (unsigned long) fedHeaderAddr << dec;
446  XCEPT_RAISE(evf::Exception, oss.str());
447  }
448 
449  // Move to the next fed trailer
450  fedTrailerAddr = fedTrailerAddr - fedSize;
451  }
452 
453  // check that we indeed end up on the starting address of the buffer
454  if ((fedTrailerAddr + sizeof(fedh_t)) != superFragAddr) {
455  stringstream oss;
456  oss << "First FED in superfragment ouf-of-bound." << " evtNumber:"
457  << res_->evtNumber_ << " iSuperFrag:" << res_->iSuperFrag_;
458  XCEPT_RAISE(evf::Exception, oss.str());
459  }
460 
461  return;
462 }
UInt_t nbErrors_
Definition: FUResource.h:183
static bool doFedIdCheck_
Definition: FUResource.h:159
unsigned short UShort_t
Definition: FUTypes.h:13
struct fedt_struct fedt_t
#define FED_TCTRLID_MASK
Definition: fed_trailer.h:37
bool gtpe_board_sense(const unsigned char *p)
unsigned int get(const unsigned char *, bool)
ResourceChecker(FUResource *const resToCheck)
static bool useEvmBoard_
Definition: FUResource.h:161
toolbox::mem::Reference MemRef_t
Definition: FUTypes.h:10
void processDataBlock(MemRef_t *bufRef)
#define FED_RBIT_MASK
Definition: FUResource.h:24
bool markFed(unsigned int i, unsigned int size, unsigned char *addr)
TRandom random
Definition: MVATrainer.cc:138
void checkDataBlockPayload(MemRef_t *bufRef)
static int const bufSize
Definition: Guid.cc:24
log4cplus::Logger log_
Definition: FUResource.h:156
evf::FUShmRawCell * shmCell_
Definition: FUResource.h:191
unsigned int sourceid
Definition: fed_header.h:32
static unsigned int gtpDaqId_
Definition: FUResource.h:198
unsigned int conscheck
Definition: fed_trailer.h:32
#define REAL_SOID_MASK
Definition: FUResource.h:23
unsigned int getlbn(const unsigned char *)
UInt_t evtNumber_
Definition: FUResource.h:167
unsigned char UChar_t
Definition: FUTypes.h:14
unsigned short compute_crc(unsigned char *buffer, unsigned int bufSize)
Definition: CRC16.h:67
UInt_t fedSize_[1024]
Definition: FUResource.h:187
unsigned char * superFragAddr(unsigned int i) const
void setEvtNumber(unsigned int evt)
Definition: FUShmRawCell.h:45
bool evm_board_sense(const unsigned char *p, size_t size)
UInt_t iSuperFrag_
Definition: FUResource.h:178
#define FED_CRCS_SHIFT
Definition: fed_trailer.h:51
FUResource *const res_
#define FED_TCTRLID
Definition: fed_trailer.h:46
unsigned int UInt_t
Definition: FUTypes.h:12
#define FED_LVL1_MASK
Definition: fed_header.h:39
#define FED_HCTRLID
Definition: fed_header.h:47
#define FED_CRCS_MASK
Definition: fed_trailer.h:40
unsigned int superFragSize(unsigned int i) const
UInt_t nbCrcErrors_
Definition: FUResource.h:184
static unsigned int gtpeId_
Definition: FUResource.h:200
unsigned int eventid
Definition: fed_header.h:33
xdaq::Application * app_
Definition: FUResource.h:194
unsigned int eventsize
Definition: fed_trailer.h:33
void setLumiSection(unsigned int)
#define FED_HCTRLID_MASK
Definition: fed_header.h:37
static unsigned int gtpEvmId_
Definition: FUResource.h:199
static bool inRange(int)
#define FED_EVSZ_MASK
Definition: fed_trailer.h:38
unsigned int gtpe_get(const unsigned char *)
bool daq_board_sense(const unsigned char *p)
bool nextEventWillHaveCRCError_
Definition: FUResource.h:196