00001
00002
00003
00004
00005
00006
00007
00008 #include "Stl3Util/gl3/gl3Conductor.h"
00009
00010 #include "Stl3Util/base/L3swap.h"
00011 #include "Stl3Util/base/realcc.h"
00012 #include "Stl3Util/base/FtfLog.h"
00013
00014 #include <time.h>
00015 #include <errno.h>
00016 #include <netinet/in.h>
00017 #include <unistd.h>
00018
00019 #ifdef GL3ONLINE
00020 #include <sys/types.h>
00021 #include <sys/socket.h>
00022 #include <fcntl.h>
00023 #endif
00024
00025
00026
00027
00028
00029
00030
00031 gl3Conductor::gl3Conductor (void){
00032 unsigned int start = realcc();
00033 sleep(1);
00034 unsigned int stop = realcc();
00035
00036
00037 ccPerMs = (double)(stop-start)/1000.;
00038
00039
00040
00041 nAlgorithms = 0;
00042 }
00043
00044
00045
00046
00047 gl3Conductor::~gl3Conductor ( ) {
00048
00049 if ( event != NULL ) delete[] event ;
00050 clearAlgorithms();
00051 if ( algorithm != NULL ) delete algorithm;
00052 if ( summary != NULL ) delete[] summary ;
00053 if ( summaryData != NULL ) free (summaryData) ;
00054 delete []tokenIndex ;
00055 }
00056
00057
00058
00059
00060 int gl3Conductor::configure (L3_CFG *cfg)
00061 {
00062 clearAlgorithms();
00063
00064 if(cfg == NULL || cfg == (L3_CFG *)-1) {
00065 ftfLog("gl3Conductor::configure: No configuration information found.\n");
00066 return 1;
00067 }
00068
00069 L3_ALGORITHMS *algos = cfg->l3_setup.gl3_algorithms;
00070
00071 for (int i=0; i<GL3_ALG_MAX_NUM; i++) {
00072 if(ntohl(algos[i].alg_id) != 0) {
00073 gl3Algorithm *algo =
00074 gl3InstantiateAlgorithm(ntohl(algos[i].alg_id));
00075
00076 if (algo == NULL) {
00077 ftfLog("gl3Conductor::configure: Instantiation of algorithm #%d failed.\n", i);
00078
00079 return 1;
00080 }
00081
00082 algo->setScaling(ntohl(algos[i].preScale),
00083 ntohl(algos[i].postScale));
00084
00085 if (algo->setParameters(ntohl(algos[i].GI1),
00086 ntohl(algos[i].GI2),
00087 ntohl(algos[i].GI3),
00088 ntohl(algos[i].GI4),
00089 ntohl(algos[i].GI5),
00090 fswap(algos[i].GF1),
00091 fswap(algos[i].GF2),
00092 fswap(algos[i].GF3),
00093 fswap(algos[i].GF4),
00094 fswap(algos[i].GF5))) {
00095 ftfLog("gl3Conductor::configure: Invalid parameters for algorithm %s (ID %d)", algo->getAlgorithmName(), algo->getAlgorithmID());
00096 return 1;
00097 }
00098
00099
00100 if(add(algo) != 0) {
00101 ftfLog("gl3Conductor::configure: Appending algorithm %s (ID %i) to list failed.\n",
00102 algo->getAlgorithmName(), algo->getAlgorithmID());
00103 return 1;
00104 }
00105
00106 algo->showConfiguration();
00107
00108 }
00109 }
00110
00111
00112 return 0;
00113 }
00114
00115
00116
00117
00118 int gl3Conductor::add( gl3Algorithm* module ) {
00119 if ( nAlgorithms >= maxAlgorithms ) {
00120 ftfLog ( "gl3Conductor::add: Max. number of algorithms reached\n" ) ;
00121 return 1;
00122 }
00123 algorithm[nAlgorithms] = module ;
00124 nAlgorithms++ ;
00125
00126 return 0 ;
00127 }
00128
00129
00130
00131
00132 void gl3Conductor::clearAlgorithms()
00133 {
00134 for (int i =0; i<nAlgorithms; i++) {
00135 if(algorithm[i]) {
00136 delete algorithm[i];
00137 algorithm[i] = NULL;
00138 }
00139 }
00140
00141 nAlgorithms = 0;
00142 }
00143
00144
00145
00146
00147
00148 int gl3Conductor::checkHistoRequest ( ) {
00149 #ifdef GL3ONLINE
00150 struct sockaddr_in remoteAddress;
00151 socklen_t sin_size = sizeof(struct sockaddr_in);
00152
00153 if ((remoteSocket = accept(socketFd, (struct sockaddr *)&remoteAddress,
00154 &sin_size)) == -1) {
00155 return 0;
00156 }
00157
00158 const int maxBytes = 100000 ;
00159 char* buffer = new char[maxBytes];
00160
00161 int nBytes = writeHistos ( maxBytes, buffer ) ;
00162
00163 if ( nBytes < 0 ) {
00164 ftfLog ( "gl3Conductor::checkHistoRequest: buffer too small \n " ) ;
00165 return 1 ;
00166 }
00167 int nSend = send(remoteSocket, buffer, nBytes, 0 ) ;
00168 ftfLog ( "gl3Conductor: %d out of %d bytes sent\n ", nSend, nBytes ) ;
00169 if ( nSend == -1) {
00170 perror("send");
00171 return 1 ;
00172 }
00173 delete []buffer ;
00174 #endif
00175 return 0 ;
00176 }
00177
00178
00179
00180
00181 int gl3Conductor::end ( ){
00182 #ifdef GL3ONLINE
00183 close ( socketFd ) ;
00184 #endif
00185 for ( int i = 0 ; i < nAlgorithms ; i++ ) {
00186 algorithm[i]->end( );
00187 }
00188 return 0 ;
00189 }
00190
00191
00192
00193
00194
00195 gl3Event* gl3Conductor::getEvent ( int token ) {
00196
00197 int index = getTokenIndex(token) ;
00198
00199 if (index < 0)
00200 return NULL;
00201 else
00202 return &(event[index]) ;
00203 }
00204
00205
00206
00207
00208
00209 int gl3Conductor::init ( ){
00210
00211 ftfLog("gl3Conductor::init: %d algos\n", nAlgorithms);
00212
00213 #ifdef GL3ONLINE
00214 l3Rates = new gl3Histo("l3rates",
00215 "L3 trigger rates",
00216 nAlgorithms+2, -2.5, (double)nAlgorithms-0.5);
00217
00218 histoList.push_back(l3Rates);
00219
00220 allocateTimingHistos();
00221 #endif
00222
00223 for ( int i = 0 ; i < nAlgorithms ; i++ ) {
00224 algorithm[i]->init();
00225 }
00226
00227 nReco = 0;
00228 return 0 ;
00229 }
00230
00231
00232
00233
00234
00235
00236 int gl3Conductor::processEvent(EventDescriptor *desc,
00237 L3_P* l3data,
00238 TrgSumData* trgSum,
00239 RawTrgDet* trgRaw)
00240 {
00241 resetTimer();
00242
00243
00244 if ( desc && desc->token != l3data->bh.token ) {
00245 ftfLog ("gl3Conductor::readEvent: token mismatch (%d and %d)\n",
00246 desc->token, l3data->bh.token);
00247 return -1;
00248 }
00249
00250 int token = l3data->bh.token;
00251
00252
00253
00254 if ( token < 0 || token > maxTokens ){
00255 ftfLog ("gl3Conductor::readEvent: %d token out of bounds\n", token );
00256 return -1;
00257 }
00258
00259
00260 int index = getFreeEventIndex();
00261 if ( index < 0 ) {
00262 ftfLog ( "gl3Conductor::readEvent: No free event container \n" ) ;
00263 return -1;
00264 }
00265 tokenIndex[token] = index;
00266
00267
00268
00269 if (event[index].readEventDescriptor(desc) != 0) {
00270 ftfLog ( "gl3Conductor::processEvent: error reading EventDescriptor\n" ) ;
00271 return -1;
00272 }
00273
00274
00275 if ( event[index].getTrgCmd() == 0 ||
00276 event[index].getTrgCmd() == 1 ||
00277 event[index].getTrgCmd() == 2 ||
00278 event[index].getTrgCmd() == 3 ) {
00279 ftfLog ("gl3Conductor::processEvent: Trigger Command 0,1,2 or 3 received\n");
00280 return 2;
00281 }
00282
00283 if ( event[index].getTrgCmd() == 5 ||
00284 event[index].getTrgCmd() == 6 ||
00285 event[index].getTrgCmd() == 7 ) {
00286 ftfLog ("gl3Conductor::processEvent: Trigger Command 5,6 or 7 received - unknown physics run type\n");
00287
00288 }
00289
00290
00291 if ( event[index].readL3Data(l3data) != 0 ) {
00292 ftfLog ( "gl3Conductor::processEvent: error reading L3 data\n" ) ;
00293 return -1;
00294 }
00295
00296
00297
00298
00299 if ( event[index].getTrgCmd() >= 8 ) {
00300
00301 return 2;
00302 }
00303
00304 timingMark();
00305
00306 if ( event[index].readTrgData(trgSum, trgRaw) != 0 ) {
00307 ftfLog ( "gl3Conductor::processEvent: error reading TRG data\n" ) ;
00308 return -1;
00309 }
00310
00311
00312 timingMark();
00313
00314
00315 int decision = 0;
00316
00317 for ( int i = 0 ; i < nAlgorithms ; i++ ) {
00318 int alg_decision = algorithm[i]->process( &(event[index]));
00319 if (alg_decision > decision) {
00320 decision = alg_decision;
00321 }
00322 timingMark();
00323 }
00324
00325
00326
00327
00328 nReco++;
00329 for ( int i = 0 ; i < nAlgorithms ; i++ ) {
00330 algorithm[i]->incrementCounters();
00331 }
00332
00333 collectSummary(token);
00334
00335 timingMark();
00336
00337 fillTimingHistos();
00338
00339 #ifdef GL3ONLINE
00340 l3Rates->Fill(-2);
00341 if (decision) {
00342 l3Rates->Fill(-1);
00343
00344 for (int i=0; i<nAlgorithms;i++) {
00345
00346 if (summaryData[index].alg[i].accept)
00347 l3Rates->Fill(i);
00348
00349
00350
00351
00352
00353
00354
00355 }
00356 }
00357
00358 if ( communicationsFlag ) {
00359 checkHistoRequest();
00360 }
00361 #endif
00362
00363 if (nAlgorithms == 0) decision=1;
00364
00365 return decision ;
00366 }
00367
00368
00369
00370
00371
00372
00373
00374 int gl3Conductor::fillSummary(int token,
00375 struct L3_summary* summaryDest,
00376 struct L3_SUMD *summaryDataDest)
00377 {
00378 int index = getTokenIndex(token);
00379 if (index < 0) return 1;
00380
00381 memcpy(summaryDest, &summary[index], sizeof(L3_summary));
00382
00383 memcpy(summaryDataDest, &summaryData[index],
00384 summaryData[index].bh.length*4);
00385
00386 return 0;
00387 }
00388
00389
00390
00391
00392 int gl3Conductor::collectSummary(int token)
00393 {
00394 int index = tokenIndex[token];
00395 if (index < 0) return 1;
00396
00397 sprintf(summaryData->bh.bank_type, CHAR_L3_SUMD);
00398 summaryData[index].bh.length =
00399 (sizeof(L3_SUMD) + (nAlgorithms-1)*sizeof(algorithm_data))/4;
00400 summaryData[index].bh.bank_id = 0;
00401 summaryData[index].bh.format_ver = 0;
00402 summaryData[index].bh.byte_order = DAQ_RAW_FORMAT_ORDER;
00403 summaryData[index].bh.format_number = 0;
00404 summaryData[index].bh.token = token;
00405 summaryData[index].bh.w9 = DAQ_RAW_FORMAT_WORD9;
00406 summaryData[index].bh.crc = 0;
00407
00408 summaryData[index].nProcessed = 0;
00409 summaryData[index].nReconstructed = nReco;
00410 summaryData[index].nAlg = nAlgorithms;
00411
00412 summary[index].accept = 0;
00413 summary[index].build = 0;
00414 summary[index].on = 0;
00415
00416 for (int i = 0; i < nAlgorithms; i++) {
00417 algorithm[i]->fillSummary(&summaryData[index].alg[i]);
00418
00419 if(summaryData[index].alg[i].on)
00420 summary[index].on |= 1<<i;
00421
00422 if(summaryData[index].alg[i].accept)
00423 summary[index].accept |= 1<<i;
00424
00425 if(summaryData[index].alg[i].build)
00426 summary[index].build |= 1<<i;
00427
00428 }
00429
00430 summary[index].nTracks = event[index].getNTracks();
00431
00432 return 0;
00433 }
00434
00435
00436
00437
00438 int gl3Conductor::releaseToken ( int token ) {
00439 int index = getTokenIndex(token);
00440 if (index < 0) return 1;
00441
00442 event[index].resetEvent();
00443 return 0;
00444 }
00445
00446
00447
00448 int gl3Conductor::resetHistos ( ) {
00449 list<gl3Histo*>::iterator histo;
00450 for(histo=histoList.begin(); histo!=histoList.end(); histo++) {
00451 (*histo)->Reset();
00452
00453 }
00454
00455 return 0 ;
00456 }
00457
00458
00459 int gl3Conductor::runStart ( int _runNumber ) {
00460 runNumber = _runNumber ;
00461 for ( int i = 0 ; i < nAlgorithms ; i++ ) {
00462 algorithm[i]->init();
00463 }
00464
00465 nReco = 0;
00466 return resetHistos ( ) ;
00467 }
00468
00469
00470
00471 int gl3Conductor::runEnd ( ) {
00472 for ( int i = 0 ; i < nAlgorithms ; i++ ) {
00473 algorithm[i]->end( );
00474 }
00475 return 0 ;
00476 }
00477
00478
00479
00480 int gl3Conductor::setCommunications ( ){
00481
00482 #ifdef GL3ONLINE
00483 struct sockaddr_in gl3Address;
00484
00485 gl3Port = 3333 ;
00486 int backLog = 5 ;
00487
00488 if ((socketFd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
00489 ftfLog("setCommunications socket: %s",strerror(errno) );
00490 return -1;
00491 }
00492 fcntl(socketFd, F_SETFL, O_NONBLOCK);
00493
00494
00495 gl3Address.sin_family = AF_INET;
00496 gl3Address.sin_port = htons(gl3Port);
00497 gl3Address.sin_addr.s_addr = INADDR_ANY;
00498 bzero(&(gl3Address.sin_zero), 8);
00499
00500 if (bind(socketFd, (struct sockaddr *)&gl3Address,
00501 sizeof(struct sockaddr)) == -1) {
00502 ftfLog("setCommunications bind: %s",strerror(errno) );
00503 return -1;
00504 }
00505
00506 if (listen(socketFd, backLog) == -1) {
00507 ftfLog("setCommunications listen: %s",strerror(errno) );
00508 return -1;
00509 }
00510 #endif
00511 return 0 ;
00512 }
00513
00514
00515
00516
00517 void gl3Conductor::setBField ( float bField ){
00518 for ( int i = 0 ; i < maxEvents ; i++ ) {
00519 event[i].setBField ( bField ) ;
00520 }
00521 }
00522
00523
00524
00525 void gl3Conductor::setHitProcessing ( int hitPro ){
00526 hitProcessing = hitPro ;
00527 for ( int i = 0 ; i < maxEvents ; i++ ) {
00528 event[i].setHitProcessing ( hitPro ) ;
00529 }
00530 }
00531
00532
00533
00534 void gl3Conductor::setMaxSectorNForTrackMerging ( int _maxSectorNForTrackMerging ){
00535 maxSectorNForTrackMerging = _maxSectorNForTrackMerging ;
00536 for ( int i = 0 ; i < maxEvents ; i++ ) {
00537 event[i].setMaxSectorNForTrackMerging ( _maxSectorNForTrackMerging ) ;
00538 }
00539 }
00540
00541
00542
00543 int gl3Conductor::setup ( St_l3_Coordinate_Transformer* _trans,
00544 int maxEventsIn, int maxAlgorithmsIn ) {
00545
00546 communicationsFlag = 1 ;
00547 event = 0 ;
00548 algorithm = 0 ;
00549 runNumber = 0 ;
00550 maxTokens = 4096 ;
00551 tokenIndex = new int[maxTokens+1];
00552
00553
00554 maxEvents = maxEventsIn ;
00555 maxAlgorithms = maxAlgorithmsIn ;
00556
00557 event = new gl3Event[maxEvents] ;
00558 summary = new L3_summary[maxEvents];
00559
00560 summaryData = (L3_SUMD*) malloc( maxEvents * (sizeof(L3_SUMD) +
00561 (maxAlgorithms-1)*sizeof(algorithm_data)));
00562
00563 algorithm = new pGl3Algorithm[maxAlgorithms] ;
00564 for (int i=0; i<maxAlgorithms;i++) algorithm[i]=NULL;
00565
00566 nEvents = 0 ;
00567 nAlgorithms = 0 ;
00568
00569 for ( int i = 0 ; i < maxTokens ; i++ ) tokenIndex[i] = 0 ;
00570
00571
00572
00573
00574 #ifdef GL3ONLINE
00575 if ( communicationsFlag ){
00576 if(setCommunications() )
00577 return -1;
00578 }
00579 #endif
00580
00581 hitProcessing = 0 ;
00582 for ( int i = 0 ; i < maxEvents ; i++ ) {
00583 event[i].setHitProcessing ( hitProcessing ) ;
00584 event[i].setCoordinateTransformer ( _trans ) ;
00585 }
00586
00587 ftfLog("analysis framework set up\n");
00588
00589 return 0 ;
00590 }
00591
00592
00593
00594 int gl3Conductor::writeHistos ( int maxBytes, char *buffer )
00595 {
00596
00597 gl3HistoContainer* container = (gl3HistoContainer *)buffer ;
00598
00599 ftfLog ( "nHistos %d \n", histoList.size() ) ;
00600 container->runNumber = runNumber ;
00601 container->nHistos = histoList.size();
00602
00603 char* pointer = (char *)&(container->buffer) ;
00604 char* endBuffer = buffer + maxBytes ;
00605 int nBytes ;
00606 int nTotalBytes = 6;
00607
00608
00609 list<gl3Histo*>::iterator histo;
00610 for(histo=histoList.begin(); histo!=histoList.end(); histo++) {
00611
00612 nBytes = (*histo)->Write ( endBuffer-pointer, pointer ) ;
00613 if ( nBytes <= 0 ) {
00614 ftfLog ( "gl3Container::writeHistos %d byte long buffer is too short \n", maxBytes ) ;
00615 return 0 ;
00616 }
00617
00618 nTotalBytes += nBytes ;
00619 if ( nTotalBytes > maxBytes ) {
00620 ftfLog ( "gl3Conductor::writeHistos: nTotalBytes %d max %d\n", nTotalBytes, maxBytes ) ;
00621 return -1 ;
00622 }
00623 pointer += nBytes * sizeof(char) ;
00624 }
00625 container->nBytes = nTotalBytes ;
00626 ftfLog ( "gl3Conductor::writeHistos: histos %d Bytes %d \n",
00627 histoList.size(), nTotalBytes ) ;
00628
00629 return nTotalBytes ;
00630 }
00631
00632
00633
00634
00635
00636
00637 int gl3Conductor::getFreeEventIndex()
00638 {
00639 int freeEventIndex = -1 ;
00640 for ( int i = 0 ; i < maxEvents ; i++ ) {
00641 if ( !(event[i].getBusy() ) ) {
00642 freeEventIndex = i ;
00643 nEvents++ ;
00644 break ;
00645 }
00646 }
00647
00648 return freeEventIndex;
00649 }
00650
00651
00652
00653
00654 int gl3Conductor::getTokenIndex(int token)
00655 {
00656 if (token < 0 || token > 4096) {
00657 ftfLog("gl3Conductor: token [%d] out of bounds \n", token );
00658 return -1;
00659 }
00660
00661 int index = tokenIndex[token];
00662
00663 if (index < 0 || index >= maxTokens) {
00664 ftfLog("gl3Conductor: event index %d out of bounds \n", token );
00665 return -2;
00666 }
00667
00668 return index;
00669 };
00670
00671
00672
00673
00674
00675
00676 void gl3Conductor::resetTimer()
00677 {
00678 lastTimeEntry=0;
00679 cpuTimes.clear();
00680 realTimes.clear();
00681
00682 cpuTimes.reserve(5+nAlgorithms);
00683 realTimes.reserve(5+nAlgorithms);
00684
00685 timingMark();
00686 }
00687
00688 void gl3Conductor::timingMark()
00689 {
00690 cpuTimes[lastTimeEntry] = clock();
00691 realTimes[lastTimeEntry] = realcc();
00692
00693 lastTimeEntry++;
00694 }
00695
00696 void gl3Conductor::allocateTimingHistos()
00697 {
00698 #ifdef GL3ONLINE
00699 timingHistos.resize(3+nAlgorithms);
00700
00701 timingHistos[0] = new gl3Histo("time_read_l3",
00702 "Timing: read L3 data",
00703 50,0,300);
00704
00705 timingHistos[1] = new gl3Histo("time_read_trg",
00706 "Timing: read TRG data",
00707 50,0,100);
00708
00709 char hid[30], htitle[100];
00710 for(int i=0; i<nAlgorithms;i++) {
00711
00712 sprintf(hid, "time_alg_%d", i);
00713 sprintf(htitle, "Timing: algorithms %d", i);
00714 timingHistos[2+i] = new gl3Histo(hid, htitle,
00715 60,0,30);
00716 }
00717
00718 timingHistos[2+nAlgorithms] = new gl3Histo("time_total",
00719 "Timing: total",
00720 50,0,300);
00721
00722
00723
00724 for(int i=0;i<timingHistos.size();i++) {
00725 histoList.push_back(timingHistos[i]);
00726 }
00727 #endif
00728 }
00729
00730 void gl3Conductor::fillTimingHistos()
00731 {
00732 #ifdef GL3ONLINE
00733 timingHistos[0]->Fill(double(realTimes[1] - realTimes[0])/ccPerMs);
00734 timingHistos[1]->Fill(double(realTimes[2] - realTimes[1])/ccPerMs);
00735
00736 for(int i=0; i<nAlgorithms;i++) {
00737 timingHistos[2+i]->Fill(double(realTimes[3+i] - realTimes[2+i])/ccPerMs);
00738 }
00739
00740 timingHistos[2+nAlgorithms]->
00741 Fill(double(realTimes[lastTimeEntry-1] - realTimes[0])/ccPerMs);
00742
00743 ftfLog("total time: %f\n",
00744 double(realTimes[lastTimeEntry-1] - realTimes[0])/ccPerMs);
00745 #endif
00746 }
00747
00748 void gl3Conductor::printTiming()
00749 {
00750 for (int i=1; i<lastTimeEntry;i++) {
00751 ftfLog("gl3Conductor: timing step %2d: CPU: %8f real: %8f\n",
00752 i, (double)cpuTimes[i]-cpuTimes[i-1]/CLOCKS_PER_SEC,
00753 (double)(realTimes[i]-realTimes[i-1])/ccPerMs);
00754 }
00755 }
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776