| [3537] | 1 | //---------------------------------------------------------------- | 
|---|
|  | 2 | // ---- classes de threads pour lecture (transfert DMA) | 
|---|
|  | 3 | //      et ecriture disque pour acquisition   BAORadio       ----- | 
|---|
|  | 4 | // LAL -      R. Ansari - Juin/Juillet 2008 | 
|---|
|  | 5 | //---------------------------------------------------------------- | 
|---|
|  | 6 |  | 
|---|
|  | 7 | #include "racqurw.h" | 
|---|
|  | 8 |  | 
|---|
|  | 9 | #include <stdlib.h> | 
|---|
|  | 10 | #include <unistd.h> | 
|---|
|  | 11 | #include <fstream> | 
|---|
| [3623] | 12 | #include <signal.h> | 
|---|
| [3537] | 13 | #include "pexceptions.h" | 
|---|
|  | 14 | #include "timestamp.h" | 
|---|
|  | 15 |  | 
|---|
|  | 16 | #include "pciewrap.h" | 
|---|
|  | 17 | #include "brpaqu.h" | 
|---|
|  | 18 | #include "minifits.h" | 
|---|
|  | 19 |  | 
|---|
| [3623] | 20 | #include "resusage.h" // Pour mesure temps elapsed/CPU ... | 
|---|
|  | 21 | #include "datatable.h" // Pour sauver les entetes de paquet | 
|---|
|  | 22 | #include <sys/time.h>  // pour gettimeofday | 
|---|
| [3674] | 23 |  | 
|---|
|  | 24 | // Si on veut que MultiDataSaver cree des fichiers avec le numero des FrameCounters... | 
|---|
|  | 25 | // define DEBUGPAQHDR | 
|---|
|  | 26 |  | 
|---|
| [3537] | 27 | //------------------------------------------------------- | 
|---|
|  | 28 | // Classe thread de lecture PCI-Express | 
|---|
|  | 29 | //------------------------------------------------------- | 
|---|
|  | 30 |  | 
|---|
| [3628] | 31 | PCIEReader::PCIEReader(PCIEWrapperInterface &pciw,uint_4 sizeFrame,uint_4 packSize ,RAcqMemZoneMgr& mem, | 
|---|
| [3623] | 32 | uint_4 nmax, BRDataFmtConv swapall) | 
|---|
|  | 33 | :   memgr(mem) , pciw_ (pciw) | 
|---|
| [3537] | 34 | { | 
|---|
| [3623] | 35 | nmax_ = nmax; | 
|---|
|  | 36 | swapall_ = swapall;   // select data swap/format conversion for BRPaquet | 
|---|
|  | 37 | stop_ = false; | 
|---|
|  | 38 | packSize_ = packSize; | 
|---|
|  | 39 | sizeFr_ =sizeFrame; | 
|---|
|  | 40 | // Pour la logique de gestion des paquets ds zone memoire | 
|---|
|  | 41 | mid_ = -2; | 
|---|
|  | 42 | targ_npaq_ = 0; | 
|---|
|  | 43 |  | 
|---|
|  | 44 | max_targ_npaq = memgr.NbPaquets(); | 
|---|
|  | 45 | mmbuf_ = NULL; | 
|---|
| [3537] | 46 | } | 
|---|
|  | 47 |  | 
|---|
| [3623] | 48 | bool PCIEReader::MZoneManage(bool fgclean)    // Retourne true si probleme | 
|---|
|  | 49 | { | 
|---|
|  | 50 | /* Pour debug | 
|---|
|  | 51 | cout << " PCIEReader::MZoneManage() mid_=" << mid_ << " arg_npaq_= " << targ_npaq_ | 
|---|
|  | 52 | << " max_targ_npaq=" << max_targ_npaq << endl; | 
|---|
|  | 53 | */ | 
|---|
|  | 54 | if (mid_ >= 0)  memgr.FreeMemZone(mid_, MemZS_Filled); | 
|---|
|  | 55 | mmbuf_ = NULL;  targ_npaq_ = 0;  mid_ = -2; | 
|---|
|  | 56 | if (fgclean)  return false; | 
|---|
|  | 57 | mid_ = memgr.FindMemZoneId(MemZA_Fill); | 
|---|
|  | 58 | mmbuf_ = memgr.GetMemZone(mid_); | 
|---|
|  | 59 | if (mmbuf_==NULL) return true; | 
|---|
|  | 60 | return false; | 
|---|
|  | 61 | } | 
|---|
|  | 62 |  | 
|---|
| [3537] | 63 | void PCIEReader::run() | 
|---|
|  | 64 | { | 
|---|
| [3623] | 65 | //Precision insuffisante  ResourceUsage ru; ru.Update();  // Pour recuperer le temps passe | 
|---|
|  | 66 | struct timeval tv1, tv2; | 
|---|
|  | 67 | gettimeofday(&tv1, NULL); | 
|---|
|  | 68 |  | 
|---|
|  | 69 | try{ | 
|---|
|  | 70 | cout << " PCIEReader::run() - Starting , NMaxMemZones=" << nmax_ | 
|---|
|  | 71 | << "memgr.NbPaquets()=" << memgr.NbPaquets() << endl; | 
|---|
| [3537] | 72 | setRC(1); | 
|---|
| [3623] | 73 |  | 
|---|
| [3658] | 74 |  | 
|---|
| [3623] | 75 | // sigaddset(&act.sa_mask,SIGINT);  // pour proteger le transfert DMA | 
|---|
|  | 76 | //sigaction(SIGINT,&act,NULL); | 
|---|
|  | 77 |  | 
|---|
| [3537] | 78 | uint_4 paqsz = memgr.PaqSize(); | 
|---|
| [3623] | 79 | uint_4 dmasz = pciw_.TransferSize(); | 
|---|
| [3643] | 80 | pciw_.StartTransfers(); | 
|---|
| [3623] | 81 |  | 
|---|
|  | 82 | Byte* Datas = NULL; | 
|---|
|  | 83 | Byte* tampon = new Byte[paqsz]; | 
|---|
|  | 84 | Byte* nextpaq = NULL; | 
|---|
|  | 85 |  | 
|---|
|  | 86 | uint_4 off_acheval = 0; | 
|---|
|  | 87 |  | 
|---|
|  | 88 | int nerrdma = 0; | 
|---|
|  | 89 | int maxerrdma = 10; | 
|---|
|  | 90 | bool fgarret = false; | 
|---|
|  | 91 |  | 
|---|
|  | 92 | uint_4 npaqfait = 0;    //  Nb total de paquets traites (DMA + decode) | 
|---|
|  | 93 |  | 
|---|
|  | 94 | ///  do{  si boucle infini | 
|---|
|  | 95 | //  for (uint_4 kmz=0; kmz<nmax_; kmz++)  { | 
|---|
|  | 96 | while (npaqfait < nmax_*memgr.NbPaquets()) { | 
|---|
|  | 97 | if (stop_) break; | 
|---|
|  | 98 | if (fgarret) break; | 
|---|
|  | 99 | // On pointe vers le debut de la zone a remplir aver le prochain DMA | 
|---|
| [3643] | 100 | Datas=pciw_.GetData(); | 
|---|
| [3623] | 101 | if (Datas == NULL) { // No data Read in DMA | 
|---|
|  | 102 | nerrdma ++; | 
|---|
|  | 103 | cout << "PCIEReaderChecker/Erreur Waiting for datas ..." << endl; | 
|---|
|  | 104 | pciw_.PrintStatus(cout); | 
|---|
|  | 105 | if (nerrdma>=maxerrdma) { fgarret = true; break; } | 
|---|
|  | 106 | } | 
|---|
|  | 107 | else {  // DMA reussi | 
|---|
|  | 108 | uint_4 curoff = 0; | 
|---|
|  | 109 | //1- On traite le paquet a cheval, rempli partiellement avec le DMA d'avant si necessaire | 
|---|
|  | 110 | if (off_acheval > 0) { | 
|---|
|  | 111 | if ((paqsz-off_acheval)< dmasz) { | 
|---|
|  | 112 | memcpy((void *)(tampon+off_acheval), (void *)Datas, paqsz-off_acheval); | 
|---|
|  | 113 | curoff = paqsz-off_acheval;  off_acheval = 0; | 
|---|
|  | 114 |  | 
|---|
|  | 115 | if ((nextpaq=NextPaqTarget()) == NULL) { | 
|---|
|  | 116 | cout << "2 PCIEReader::run()/Error NextPaqTarget() returned NULL ->STOP 9" << endl; | 
|---|
|  | 117 | setRC(9);  fgarret=true; break; | 
|---|
|  | 118 | } | 
|---|
|  | 119 | BRPaquet paq(tampon, nextpaq, paqsz, swapall_); | 
|---|
|  | 120 | npaqfait++;  // Ne pas oublier le compteur de paquets faits | 
|---|
|  | 121 | } | 
|---|
|  | 122 | else { | 
|---|
|  | 123 | memcpy((void *)(tampon+off_acheval), (void *)Datas, dmasz); | 
|---|
|  | 124 | curoff =dmasz; | 
|---|
|  | 125 | off_acheval = (dmasz+off_acheval); | 
|---|
|  | 126 | } | 
|---|
|  | 127 | } | 
|---|
|  | 128 | //2- On traite les paquets complet qui se trouvent dans la zone du DMA | 
|---|
|  | 129 | while((curoff+paqsz)<=dmasz) { | 
|---|
|  | 130 | //          BRPaquet paq((Byte*)(Datas)+((paqsz*j)), nextdma+j*paqsz, paqsz, swapall_); | 
|---|
|  | 131 | if ((nextpaq=NextPaqTarget()) == NULL) { | 
|---|
|  | 132 | cout << "3 PCIEReader::run()/Error NextPaqTarget() returned NULL ->STOP 9" << endl; | 
|---|
|  | 133 | setRC(9);  fgarret=true; break; | 
|---|
|  | 134 | } | 
|---|
|  | 135 | BRPaquet paq(Datas+curoff, nextpaq, paqsz, swapall_); | 
|---|
|  | 136 | curoff += paqsz;  // On avance l'index dans le buffer du DMA | 
|---|
|  | 137 | npaqfait++;  // Ne pas oublier le compteur de paquets faits | 
|---|
|  | 138 | }  // -- FIN traitement des paquets complets ds un DMA | 
|---|
|  | 139 | //3- On copie si besoin la fin du DMA dans la zone tampon | 
|---|
|  | 140 | if (curoff < dmasz) { | 
|---|
|  | 141 | if (fgarret) break;  // pour sortir si l'on est passe par un STOP 9 | 
|---|
|  | 142 | off_acheval = dmasz-curoff; | 
|---|
|  | 143 | memcpy(tampon, (void*)(Datas+curoff), off_acheval); | 
|---|
|  | 144 | curoff += off_acheval; | 
|---|
|  | 145 | } | 
|---|
|  | 146 | }  //   Traitement d'un DMA OK | 
|---|
|  | 147 | } | 
|---|
|  | 148 | //  }while(!stop_); | 
|---|
|  | 149 |  | 
|---|
|  | 150 |  | 
|---|
|  | 151 | gettimeofday(&tv2, NULL); | 
|---|
|  | 152 | double tmelaps2 = (tv2.tv_sec-tv1.tv_sec)*1000.+(tv2.tv_usec-tv1.tv_usec)/1000.; | 
|---|
|  | 153 | if (tmelaps2<0.1) tmelaps2=0.1; | 
|---|
|  | 154 | cout << " ------------------ PCIEReader::run()-End summary -------------------" << endl; | 
|---|
|  | 155 | cout << " PCIEReader/Info TotTransfer=" << pciw_.TotTransferBytes()/1024 | 
|---|
|  | 156 | << " kb , ElapsTime=" << tmelaps2 << " ms ->" | 
|---|
|  | 157 | << (double)pciw_.TotTransferBytes()/tmelaps2 << " kb/s" << endl; | 
|---|
|  | 158 | cout << " --------------------------------------------------------------------" << endl; | 
|---|
|  | 159 |  | 
|---|
|  | 160 | MZoneManage(true); | 
|---|
|  | 161 | delete [] tampon; | 
|---|
|  | 162 |  | 
|---|
|  | 163 | }catch (PException& exc) { | 
|---|
|  | 164 | cout << " PCIEREADER::run()/catched PException " << exc.Msg() << endl; | 
|---|
|  | 165 | setRC(3); | 
|---|
|  | 166 | return; | 
|---|
|  | 167 | } | 
|---|
|  | 168 | catch(...) { | 
|---|
|  | 169 | cout << "  PCIEREADER::run()/catched unknown ... exception " << endl; | 
|---|
|  | 170 | setRC(4); | 
|---|
|  | 171 | return; | 
|---|
|  | 172 | } | 
|---|
| [3537] | 173 | setRC(0); | 
|---|
| [3623] | 174 |  | 
|---|
| [3537] | 175 | return; | 
|---|
|  | 176 | } | 
|---|
|  | 177 |  | 
|---|
|  | 178 |  | 
|---|
| [3623] | 179 | void PCIEReader::Stop() | 
|---|
|  | 180 | { | 
|---|
|  | 181 | // cout << " PCIEReader::Stop() -------------> STOP" <<endl; | 
|---|
|  | 182 | stop_ = true; | 
|---|
|  | 183 | return; | 
|---|
|  | 184 | } | 
|---|
| [3537] | 185 |  | 
|---|
| [3623] | 186 |  | 
|---|
| [3537] | 187 | //------------------------------------------------------- | 
|---|
|  | 188 | // Classe thread de sauvegarde sur fichiers | 
|---|
|  | 189 | //------------------------------------------------------- | 
|---|
|  | 190 |  | 
|---|
| [3623] | 191 | DataSaver::DataSaver(RAcqMemZoneMgr& mem, string& path, uint_4 nfiles, uint_4 nblocperfile, bool savesig) | 
|---|
| [3537] | 192 | :  memgr(mem) | 
|---|
|  | 193 | { | 
|---|
| [3623] | 194 | nfiles_ = nfiles; | 
|---|
|  | 195 | nblocperfile_ = nblocperfile; | 
|---|
|  | 196 | nmax_ = nblocperfile_*nfiles_; | 
|---|
|  | 197 | savesig_ = savesig;  // Si false, pas d'ecriture des fichiers FITS du signal | 
|---|
| [3537] | 198 | stop_ = false; | 
|---|
|  | 199 | path_ = path; | 
|---|
|  | 200 | } | 
|---|
| [3623] | 201 | void DataSaver::Stop() | 
|---|
|  | 202 | { | 
|---|
|  | 203 | // cout<< " DataSaver:Stop ........ " << endl; | 
|---|
|  | 204 | stop_=true; | 
|---|
| [3537] | 205 |  | 
|---|
| [3623] | 206 | } | 
|---|
| [3537] | 207 | void DataSaver::run() | 
|---|
|  | 208 | { | 
|---|
|  | 209 | setRC(1); | 
|---|
| [3623] | 210 | BRPaqChecker pcheck;  // Verification/comptage des paquets | 
|---|
|  | 211 |  | 
|---|
| [3537] | 212 | try { | 
|---|
|  | 213 | TimeStamp ts; | 
|---|
| [3623] | 214 | cout << " DataSaver::run() - Starting " << ts << " NbFiles=" << nfiles_ << " NBloc/File=" | 
|---|
|  | 215 | << nblocperfile_ << " NMaxMemZones=" << nmax_ << endl; | 
|---|
| [3537] | 216 | char fname[512]; | 
|---|
| [3623] | 217 |  | 
|---|
| [3537] | 218 | sprintf(fname,"%s/saver.log",path_.c_str()); | 
|---|
|  | 219 | ofstream filog(fname); | 
|---|
| [3644] | 220 | filog << " DataSaver::run() - starting log file " << ts << endl; | 
|---|
| [3623] | 221 | filog << " NbFiles=" << nfiles_ << " NBloc/File="  << nblocperfile_ << " NMaxMemZones=" << nmax_ << endl; | 
|---|
|  | 222 |  | 
|---|
|  | 223 | DataTable dt; | 
|---|
|  | 224 | dt.AddLongColumn("TimeTag"); | 
|---|
|  | 225 | dt.AddIntegerColumn("FrameCounter"); | 
|---|
|  | 226 | dt.AddIntegerColumn("FrameLength"); | 
|---|
|  | 227 | dt.AddIntegerColumn("Num"); | 
|---|
|  | 228 | DataTableRow dtr = dt.EmptyRow(); | 
|---|
|  | 229 | uint_8 timtag = 0; | 
|---|
|  | 230 | uint_4 numpaq = 0; | 
|---|
|  | 231 | bool dthead = false;  // Mettre a false pour ne pas remplir DataTable Headers | 
|---|
| [3537] | 232 |  | 
|---|
| [3623] | 233 |  | 
|---|
|  | 234 | uint_4 fnum=0; | 
|---|
| [3537] | 235 | uint_4 paqsz = memgr.PaqSize(); | 
|---|
| [3658] | 236 | cout << " ============================ DataSaver::run() PaqSize " << paqsz <<endl; | 
|---|
| [3644] | 237 | bool fgnulldev = false; | 
|---|
|  | 238 | if (path_ == "/dev/null") { | 
|---|
|  | 239 | cout << " DataSaver::run()/Warning /dev/null path specified, filenames=/dev/null" << endl; | 
|---|
|  | 240 | fgnulldev = true; | 
|---|
|  | 241 | } | 
|---|
| [3623] | 242 | for (uint_4 nbFile=0;nbFile<nfiles_ ;nbFile++) { | 
|---|
|  | 243 | if (stop_ )   break; | 
|---|
| [3644] | 244 | if (fgnulldev) strcpy(fname,"/dev/null"); | 
|---|
|  | 245 | else sprintf(fname,"%s/HDRfits%d.txt",path_.c_str(),fnum); | 
|---|
| [3623] | 246 | ofstream header(fname); | 
|---|
|  | 247 |  | 
|---|
|  | 248 | BRPaquet paq0(NULL, NULL, paqsz); | 
|---|
|  | 249 | uint_4 npaqperfile = memgr.NbPaquets()*nblocperfile_;  // Nombre de paquets ecrits dans un fichier | 
|---|
|  | 250 |  | 
|---|
|  | 251 | MiniFITSFile mff; | 
|---|
|  | 252 | if (savesig_) { //Reza - Ouverture conditionnel fichier | 
|---|
| [3644] | 253 | if (fgnulldev) strcpy(fname,"/dev/null"); | 
|---|
|  | 254 | else sprintf(fname,"%s/signal%d.fits",path_.c_str(),(int)fnum++); | 
|---|
| [3623] | 255 | mff.Open(fname,MF_Write);  //Reza - Ouverture conditionnel fichier | 
|---|
| [3640] | 256 | // Entete correspondant a l'ecriture tout le paquet - trailer compris (modif Mai 2009) | 
|---|
|  | 257 | mff.setDTypeNaxis(MF_Byte, paq0.PaquetSize(), npaqperfile); | 
|---|
| [3658] | 258 |  | 
|---|
| [3640] | 259 | // Sans TRAILER de paquet mff.setDTypeNaxis(MF_Byte, paq0.DataSize()+paq0.HeaderSize(), npaqperfile); | 
|---|
| [3537] | 260 | } | 
|---|
| [3623] | 261 | else sprintf(fname,"MemDataBloc[%d]-NoDataFile",(int)fnum++); | 
|---|
|  | 262 |  | 
|---|
|  | 263 | for (uint_4 kmz=0; kmz<nblocperfile_; kmz++) { | 
|---|
|  | 264 | if (stop_) break; | 
|---|
|  | 265 | //DBG cout << " DataSaver::run()- nbFile=" << nbFile << " kmz=" << kmz << endl; | 
|---|
|  | 266 | int mid = memgr.FindMemZoneId(MemZA_Save); | 
|---|
|  | 267 | Byte* buff = memgr.GetMemZone(mid); | 
|---|
|  | 268 | if (buff == NULL) { | 
|---|
|  | 269 | cout << " DataSaver::run()/ERROR memgr.GetMemZone(" << mid << ") -> NULL" << endl; | 
|---|
|  | 270 | setRC(2); | 
|---|
|  | 271 | return; | 
|---|
|  | 272 | } | 
|---|
|  | 273 | for(uint_4 i=0; i<memgr.NbPaquets(); i++) { | 
|---|
|  | 274 |  | 
|---|
|  | 275 | BRPaquet paq(NULL, buff+i*paqsz, paqsz); | 
|---|
|  | 276 | pcheck.Check(paq);   // Verification du paquet / FrameCounter | 
|---|
| [3643] | 277 | if (savesig_) | 
|---|
|  | 278 | header << hex << paq.HDRMarker() << " " << paq.TRLMarker() << " " | 
|---|
|  | 279 | << paq.TimeTag2()<< " "<< paq.TimeTag1()<< " " | 
|---|
|  | 280 | << paq.FrameCounter() << " " << paq.PaqLen()  << endl; | 
|---|
| [3623] | 281 |  | 
|---|
|  | 282 | if (dthead) {  // Remplissage DataTable entetes paquets | 
|---|
|  | 283 | timtag = (uint_8)paq.TimeTag2()*0x100000000ULL+paq.TimeTag1(); | 
|---|
|  | 284 | dtr[0] = timtag; | 
|---|
|  | 285 | dtr[1] = paq.FrameCounter(); | 
|---|
|  | 286 | dtr[2] = paq.PaqLen(); | 
|---|
|  | 287 | dtr[3] = numpaq++; | 
|---|
|  | 288 | dt.AddRow(dtr); | 
|---|
|  | 289 | } | 
|---|
|  | 290 |  | 
|---|
|  | 291 | if (savesig_) // Reza - Ecriture conditionnel fichier fits signal | 
|---|
| [3640] | 292 | mff.WriteB(paq.Header(),paq.PaquetSize()); // ecriture tout le paquet (modif Mai 2009) | 
|---|
|  | 293 | //  mff.WriteB(paq.Data1(), paq.DataSize()); | 
|---|
|  | 294 | //  mff.WriteB(paq.Header(),paq.DataSize()+paq.HeaderSize()); // ecriture datas + header | 
|---|
| [3623] | 295 | } | 
|---|
|  | 296 | memgr.FreeMemZone(mid, MemZS_Saved); | 
|---|
| [3537] | 297 | } | 
|---|
| [3623] | 298 | ts.SetNow(); | 
|---|
|  | 299 | filog << ts << " : OK data file  " << fname << endl; | 
|---|
|  | 300 | cout << " DataSaver::run() " << ts << " : OK data file  " << fname << endl; | 
|---|
| [3537] | 301 | } | 
|---|
| [3623] | 302 | if (dthead) { | 
|---|
|  | 303 | cout << dt; | 
|---|
|  | 304 | char fname2[256]; | 
|---|
|  | 305 | sprintf(fname2,"%s/headers.ppf",path_.c_str()); | 
|---|
|  | 306 | POutPersist po(fname2); | 
|---|
|  | 307 | po << dt; | 
|---|
|  | 308 | } | 
|---|
|  | 309 | cout << " --------------------  DataSaver::run() -------------------- " << endl; | 
|---|
|  | 310 | pcheck.Print(cout); | 
|---|
|  | 311 | cout << " ---------------------------------------------------------- " << endl; | 
|---|
|  | 312 | ts.SetNow(); | 
|---|
|  | 313 | pcheck.Print(filog); | 
|---|
|  | 314 | filog << " DataSaver::run() - End of processing/run() " << ts << endl; | 
|---|
|  | 315 |  | 
|---|
| [3537] | 316 | } | 
|---|
|  | 317 | catch (MiniFITSException& exc) { | 
|---|
|  | 318 | cout << " DataSaver::run()/catched MiniFITSException " << exc.Msg() << endl; | 
|---|
|  | 319 | setRC(3); | 
|---|
|  | 320 | return; | 
|---|
|  | 321 | } | 
|---|
|  | 322 | catch(...) { | 
|---|
|  | 323 | cout << " DataSaver::run()/catched unknown ... exception " << endl; | 
|---|
|  | 324 | setRC(4); | 
|---|
|  | 325 | return; | 
|---|
|  | 326 | } | 
|---|
|  | 327 | setRC(0); | 
|---|
|  | 328 | return; | 
|---|
|  | 329 | } | 
|---|
|  | 330 |  | 
|---|
|  | 331 |  | 
|---|
| [3623] | 332 |  | 
|---|
|  | 333 |  | 
|---|
|  | 334 | //---------------------------------------------------------------------------------------------------------- | 
|---|
|  | 335 | // Classe thread de lecture PCI-Express + Check pour tests de verification de debit/etc avec un seul thread | 
|---|
|  | 336 | //---------------------------------------------------------------------------------------------------------- | 
|---|
|  | 337 |  | 
|---|
| [3672] | 338 | PCIEReaderChecker::PCIEReaderChecker(PCIEWrapperInterface &pciw, uint_4 sizeFrame,uint_4 packSize, RAcqMemZoneMgr& mem, | 
|---|
|  | 339 | uint_4 nmax, BRDataFmtConv swapall) | 
|---|
| [3623] | 340 | :   memgr(mem) , pciw_ (pciw) | 
|---|
|  | 341 | { | 
|---|
|  | 342 | nmax_ = nmax; | 
|---|
|  | 343 | swapall_ = swapall;   // select data swap/format conversion for BRPaquet | 
|---|
|  | 344 | stop_ = false; | 
|---|
|  | 345 | packSize_ = packSize; | 
|---|
|  | 346 | sizeFr_ =sizeFrame; | 
|---|
|  | 347 | } | 
|---|
|  | 348 | void PCIEReaderChecker::run() | 
|---|
|  | 349 | { | 
|---|
|  | 350 |  | 
|---|
|  | 351 | struct timeval tv1, tv2; | 
|---|
|  | 352 | gettimeofday(&tv1, NULL); | 
|---|
|  | 353 |  | 
|---|
|  | 354 | cout << " PCIEReaderChecker::run() - Starting , NMaxMemZones=" << nmax_ | 
|---|
|  | 355 | << " memgr.NbPaquets()=" << memgr.NbPaquets() << endl; | 
|---|
|  | 356 | setRC(1); | 
|---|
|  | 357 | cout << " ... RAcqMemZoneMgr not used - using s fixed memory location for packets decoding ..." << endl; | 
|---|
|  | 358 |  | 
|---|
| [3658] | 359 |  | 
|---|
| [3623] | 360 | // sigaddset(&act.sa_mask,SIGINT);  // pour proteger le transfert DMA | 
|---|
|  | 361 | //sigaction(SIGINT,&act,NULL); | 
|---|
|  | 362 | uint_4 paqsz = memgr.PaqSize(); | 
|---|
|  | 363 | uint_4 dmasz = pciw_.TransferSize(); | 
|---|
| [3643] | 364 | pciw_.StartTransfers(); | 
|---|
| [3623] | 365 |  | 
|---|
|  | 366 | BRPaqChecker pcheck;  // Verification/comptage des paquets | 
|---|
|  | 367 |  | 
|---|
|  | 368 | Byte* Datas = NULL; | 
|---|
| [3658] | 369 | Byte* locdata = new Byte[paqsz*memgr.NbPaquets()*memgr.NbZones()]; | 
|---|
| [3623] | 370 | Byte* tampon = new Byte[paqsz]; | 
|---|
|  | 371 |  | 
|---|
|  | 372 | uint_4 off_acheval = 0; | 
|---|
|  | 373 |  | 
|---|
|  | 374 | int nerrdma = 0; | 
|---|
|  | 375 | int maxerrdma = 10; | 
|---|
|  | 376 | bool fgarret = false; | 
|---|
|  | 377 | for (uint_4 kmz=0; kmz<nmax_; kmz++)  { | 
|---|
|  | 378 | if (stop_) break; | 
|---|
|  | 379 | if (fgarret) break; | 
|---|
|  | 380 |  | 
|---|
| [3658] | 381 | Byte* nextdma = locdata+((kmz%memgr.NbZones())*(paqsz*memgr.NbPaquets())); | 
|---|
| [3623] | 382 | uint_4 npaqfait = 0; | 
|---|
|  | 383 | //      for (uint_4 i=0; i<memgr.NbPaquets(); i += pktInDMATr) {  // attention pktInDMATr paquets dans 1 seul DMA | 
|---|
|  | 384 | while (npaqfait < memgr.NbPaquets()) { | 
|---|
|  | 385 | if (fgarret) break; | 
|---|
|  | 386 | // On pointe vers le debut de la zone a remplir aver le prochain DMA | 
|---|
|  | 387 | //-- Zone memoire locale Byte* nextdma = buff+i*paqsz; | 
|---|
| [3643] | 388 | Datas=pciw_.GetData(); | 
|---|
| [3623] | 389 |  | 
|---|
|  | 390 | if (Datas == NULL) { // No data Read in DMA | 
|---|
|  | 391 | nerrdma ++; | 
|---|
|  | 392 | cout << "PCIEReaderChecker/Erreur Waiting for datas ..." << endl; | 
|---|
|  | 393 | pciw_.PrintStatus(cout); | 
|---|
|  | 394 | if (nerrdma>=maxerrdma) { fgarret = true; break; } | 
|---|
|  | 395 | } | 
|---|
|  | 396 | else { | 
|---|
|  | 397 | uint_4 curoff = 0; | 
|---|
|  | 398 | //1- On traite le paquet a cheval, rempli partiellement avec le DMA d'avant si necessaire | 
|---|
|  | 399 | //      if (off_acheval > 0) { | 
|---|
|  | 400 | //  memcpy((void *)(tampon+off_acheval), (void *)Datas, paqsz-off_acheval); | 
|---|
|  | 401 | //  curoff = paqsz-off_acheval;  off_acheval = 0; | 
|---|
|  | 402 |  | 
|---|
|  | 403 | // BRPaquet paq(tampon, locdata, paqsz, swapall_); | 
|---|
|  | 404 | //  npaqfait++;  // Ne pas oublier le compteur de paquets faits | 
|---|
|  | 405 | //  pcheck.Check(paq);   // Verification du paquet / FrameCounter | 
|---|
|  | 406 | //} | 
|---|
|  | 407 | if (off_acheval > 0) { | 
|---|
|  | 408 | if ((paqsz-off_acheval)< dmasz) { | 
|---|
|  | 409 | memcpy((void *)(tampon+off_acheval), (void *)Datas, paqsz-off_acheval); | 
|---|
|  | 410 | curoff = paqsz-off_acheval;  off_acheval = 0; | 
|---|
|  | 411 |  | 
|---|
|  | 412 | BRPaquet paq(tampon, locdata, paqsz, swapall_); | 
|---|
|  | 413 | npaqfait++;  // Ne pas oublier le compteur de paquets faits | 
|---|
|  | 414 | pcheck.Check(paq);   // Verification du paquet / FrameCounter | 
|---|
|  | 415 | } | 
|---|
|  | 416 | else { | 
|---|
|  | 417 | memcpy((void *)(tampon+off_acheval), (void *)Datas, dmasz); | 
|---|
|  | 418 | curoff =dmasz; | 
|---|
|  | 419 | off_acheval = (dmasz+off_acheval); | 
|---|
|  | 420 | } | 
|---|
|  | 421 | } | 
|---|
|  | 422 | //2- On traite les paquets complet qui se trouvent dans la zone du DMA | 
|---|
|  | 423 | while((curoff+paqsz)<=dmasz) { | 
|---|
|  | 424 | //        BRPaquet paq((Byte*)(Datas)+((paqsz*j)), nextdma+j*paqsz, paqsz, swapall_); | 
|---|
| [3658] | 425 | //  BRPaquet paq(Datas+curoff, locdata, paqsz, swapall_); | 
|---|
|  | 426 | BRPaquet paq(Datas+curoff, nextdma+npaqfait*paqsz, paqsz, swapall_); | 
|---|
| [3623] | 427 | curoff += paqsz;  // On avance l'index dans le buffer du DMA | 
|---|
|  | 428 | npaqfait++;  // Ne pas oublier le compteur de paquets faits | 
|---|
|  | 429 | pcheck.Check(paq);   // Verification du paquet / FrameCounter | 
|---|
|  | 430 | }  // -- FIN traitement des paquets complets ds un DMA | 
|---|
|  | 431 | //3- On copie si besoin la fin du DMA dans la zone tampon | 
|---|
|  | 432 | if (curoff < dmasz) { | 
|---|
|  | 433 | off_acheval = dmasz-curoff; | 
|---|
|  | 434 | memcpy(tampon, (void*)(Datas+curoff), off_acheval); | 
|---|
|  | 435 | curoff += off_acheval; | 
|---|
|  | 436 | } | 
|---|
|  | 437 | }  //   Traitement d'un DMA OK | 
|---|
|  | 438 |  | 
|---|
|  | 439 | }  // Fin boucle de remplissage d'une zone memoire | 
|---|
|  | 440 | } //  Fin boucle sur les zones | 
|---|
|  | 441 |  | 
|---|
|  | 442 | setRC(0); | 
|---|
|  | 443 | gettimeofday(&tv2, NULL); | 
|---|
|  | 444 | double tmelaps2 = (tv2.tv_sec-tv1.tv_sec)*1000.+(tv2.tv_usec-tv1.tv_usec)/1000.; | 
|---|
|  | 445 | if (tmelaps2<0.1) tmelaps2=0.1; | 
|---|
|  | 446 | cout << " ------------------ PCIEReaderChecker::run()-End summary -------------------" << endl; | 
|---|
|  | 447 | cout << " PCIEReaderChecker/Info TotTransfer=" << pciw_.TotTransferBytes()/1024 | 
|---|
|  | 448 | << " kb , ElapsTime=" << tmelaps2 << " ms ->" | 
|---|
|  | 449 | << (double)pciw_.TotTransferBytes()/tmelaps2 << " kb/s" << endl; | 
|---|
|  | 450 | pcheck.Print(cout); | 
|---|
|  | 451 | cout << " --------------------------------------------------------------------" << endl; | 
|---|
|  | 452 |  | 
|---|
|  | 453 | delete [] locdata; | 
|---|
|  | 454 | delete [] tampon; | 
|---|
|  | 455 |  | 
|---|
|  | 456 | return; | 
|---|
|  | 457 | } | 
|---|
|  | 458 | void PCIEReaderChecker::Stop() | 
|---|
|  | 459 | { | 
|---|
|  | 460 | // cout << " PCIEReaderChecker::stop()  ........ STOP" <<endl; | 
|---|
|  | 461 | stop_ = true; | 
|---|
|  | 462 |  | 
|---|
|  | 463 | } | 
|---|
| [3658] | 464 | //////////////////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 465 | //---------------------------------------------------------------------------------------------------------- | 
|---|
|  | 466 | // Classe thread de lecture PCI-Express + Check pour tests de verification de debit/etc avec un seul thread | 
|---|
|  | 467 | //---------------------------------------------------------------------------------------------------------- | 
|---|
|  | 468 |  | 
|---|
|  | 469 | /* --Methode-- */ | 
|---|
| [3672] | 470 | PCIEMultiReader::PCIEMultiReader(vector<PCIEWrapperInterface*> vec_pciw, RAcqMemZoneMgr& mem, BRParList const& par) | 
|---|
|  | 471 | :   memgr(mem), par_(par), vec_pciw_ (vec_pciw) | 
|---|
| [3658] | 472 | { | 
|---|
| [3672] | 473 | nmax_ = par_.MaxNbBlocs(); | 
|---|
|  | 474 | swapall_ = par_.GetDataConvFg();      // select data swap/format conversion for BRPaquet | 
|---|
| [3658] | 475 | stop_ = false; | 
|---|
| [3672] | 476 | packSize_ = par_.RecvPaquetSize(); | 
|---|
| [3658] | 477 | packSizeInMgr_=memgr.PaqSize(); | 
|---|
| [3672] | 478 | sizeFr_=par_.DMASizeBytes(); | 
|---|
| [3658] | 479 | if (vec_pciw.size() != memgr.NbFibres()) { | 
|---|
|  | 480 | cout << " PCIEMultiReader()PbArgs: vec_pciw.size()= " << vec_pciw.size() << " memgr.NbFibres()=" <<memgr.NbFibres()<< endl; | 
|---|
|  | 481 | throw ParmError("PCIEMultiReader:ERROR/ arguments incompatibles vec_pciw.size() != memgr.NbFibres() "); | 
|---|
|  | 482 | } | 
|---|
|  | 483 | if (vec_pciw.size() > MAXNBFIB) | 
|---|
|  | 484 | throw ParmError("PCIEMultiReader:ERROR/  vec_pciw.size() > MAXNBFIB "); | 
|---|
|  | 485 | nbDma_= vec_pciw.size(); | 
|---|
|  | 486 | mid_=-2; | 
|---|
|  | 487 | mmbuf_=NULL; | 
|---|
|  | 488 | max_targ_npaq = memgr.NbPaquets(); | 
|---|
|  | 489 | for (int fid=0 ; fid<(int)nbDma_ ;fid++) mmbufib_[fid]=NULL; | 
|---|
|  | 490 | } | 
|---|
|  | 491 |  | 
|---|
|  | 492 | /* --Methode-- */ | 
|---|
|  | 493 | void PCIEMultiReader::run() | 
|---|
|  | 494 | { | 
|---|
|  | 495 |  | 
|---|
|  | 496 | struct timeval tv1,tv2; | 
|---|
|  | 497 | gettimeofday(&tv1, NULL); | 
|---|
|  | 498 |  | 
|---|
|  | 499 | cout << " PCIEMultiReader::run() - Starting , NMaxMemZones=" << nmax_ | 
|---|
| [3675] | 500 | << " memgr.NbPaquets(),PaqSz=" << memgr.NbPaquets() << " ," << memgr.PaqSize() | 
|---|
|  | 501 | << " DMA-Paqsize " << packSize_ << "  " << BRPaquet::FmtConvToString(swapall_) << endl; | 
|---|
| [3658] | 502 | setRC(1); | 
|---|
|  | 503 |  | 
|---|
|  | 504 | // sigaddset(&act.sa_mask,SIGINT);  // pour proteger le transfert DMA | 
|---|
|  | 505 | //sigaction(SIGINT,&act,NULL); | 
|---|
| [3675] | 506 | uint_4 paqszmm = memgr.PaqSize(); | 
|---|
| [3658] | 507 | uint_4 paqsz =  packSize_; | 
|---|
|  | 508 | uint_4 dmasz = vec_pciw_[0]->TransferSize(); | 
|---|
|  | 509 | vec_pciw_[0]->StartTransfers(); | 
|---|
|  | 510 |  | 
|---|
|  | 511 | BRPaqChecker pcheck[MAXNBFIB];  // Verification/comptage des paquets | 
|---|
|  | 512 | Byte* Datas[MAXNBFIB]; | 
|---|
|  | 513 | Byte* tampon[MAXNBFIB] ; | 
|---|
| [3674] | 514 | Byte* predtampon=NULL;  // tampon de recopie pour la reduction des tailles de paquets | 
|---|
| [3658] | 515 | Byte* nextpaq=NULL; | 
|---|
|  | 516 | uint_4 off_acheval=0; | 
|---|
|  | 517 |  | 
|---|
|  | 518 | int nerrdma = 0; | 
|---|
|  | 519 | int maxerrdma = 10; | 
|---|
|  | 520 | bool fgarret = false; | 
|---|
|  | 521 |  | 
|---|
|  | 522 | // Initialisation des tampons pour recopie des paquets a cheval pour chaque DMA | 
|---|
|  | 523 | for (int i=0;i< (int)nbDma_ ;i++) { | 
|---|
|  | 524 | tampon[i]=   new Byte[paqsz]; | 
|---|
|  | 525 | } | 
|---|
| [3674] | 526 | bool fgredpaq=par_.fgreducpsize; | 
|---|
|  | 527 | if (fgredpaq) { | 
|---|
|  | 528 | cout << " PCIEMultiReader::run() - PaquetSizeReduction - RedSize=" << par_.redpqsize | 
|---|
|  | 529 | << " Offset=" << par_.reducoffset << " " << ((par_.reducneedcopy)?"NeedCopy":"NOCopy") | 
|---|
|  | 530 | << "  " << BRPaquet::ReducActionToString(par_.pqreducmode) << endl; | 
|---|
|  | 531 | predtampon = new Byte[paqsz]; | 
|---|
|  | 532 | } | 
|---|
|  | 533 |  | 
|---|
|  | 534 | #ifdef DEBUGPAQHDR | 
|---|
| [3658] | 535 | ofstream header[MAXNBFIB]; | 
|---|
|  | 536 | for(uint_4 fib=0; fib<nbDma_; fib++) { | 
|---|
|  | 537 | char hfnm[128]; | 
|---|
|  | 538 | sprintf(hfnm, "./HDRCountPaqs%d.txt", fib); | 
|---|
|  | 539 | header[fib].open(hfnm); | 
|---|
|  | 540 | } | 
|---|
| [3674] | 541 | #endif | 
|---|
| [3658] | 542 | uint_4 npaqfait[MAXNBFIB] ; | 
|---|
|  | 543 | for (int i=0;i< (int)nbDma_ ;i++) npaqfait[i]=0; | 
|---|
|  | 544 | // Byte* nextdma = locdata+((kmz%memgr.NbZones())*(paqsz*memgr.NbPaquets())); | 
|---|
|  | 545 | uint_4 npaqfaitg = 0; | 
|---|
|  | 546 | //      for (uint_4 i=0; i<memgr.NbPaquets(); i += pktInDMATr) {  // attention pktInDMATr paquets dans 1 seul DMA | 
|---|
|  | 547 | while (npaqfaitg < nmax_*memgr.NbPaquets()) {  // Boucle global G | 
|---|
|  | 548 | if (fgarret) break; | 
|---|
|  | 549 | if (stop_) break; | 
|---|
|  | 550 |  | 
|---|
|  | 551 | // Lancement des DMA | 
|---|
|  | 552 | for (int dma=0; dma < (int)nbDma_ ;dma++) vec_pciw_[dma]->StartTransfers(); | 
|---|
|  | 553 |  | 
|---|
|  | 554 | // On pointe vers le debut de la zone a remplir aver le prochain DMA | 
|---|
|  | 555 | //-- Zone memoire locale Byte* nextdma = buff+i*paqsz; | 
|---|
|  | 556 |  | 
|---|
|  | 557 | bool fgbaddma=false; | 
|---|
|  | 558 | // On boucle sur les nbDma_ en attente de leurs terminaison | 
|---|
|  | 559 | for (int dma=0; dma <(int) nbDma_ ;dma++)  { | 
|---|
|  | 560 | Datas[dma]=vec_pciw_[dma]->GetData(); | 
|---|
|  | 561 | if (Datas[dma] == NULL) { // No data Read in DMA | 
|---|
|  | 562 | nerrdma ++;   fgbaddma=true; | 
|---|
|  | 563 | cout << "PCIEMultiReaderChecker/Erreur Waiting for datas ..." << endl; | 
|---|
|  | 564 | vec_pciw_[dma]->PrintStatus(cout); | 
|---|
|  | 565 | if (nerrdma>=maxerrdma) { fgarret = true; break; } | 
|---|
|  | 566 | } | 
|---|
|  | 567 | } | 
|---|
|  | 568 | if (fgbaddma) continue; | 
|---|
|  | 569 | uint_4 curoff=0; | 
|---|
|  | 570 | //1- On traite le paquet a cheval, rempli partiellement avec le DMA d'avant si necessaire pour les n fibres | 
|---|
|  | 571 | if (off_acheval  > 0) {  // IF Numero B | 
|---|
|  | 572 | if ((paqsz-off_acheval)< dmasz) {  // IF Numero A | 
|---|
|  | 573 | for(uint_4 fib=0; fib<nbDma_; fib++) | 
|---|
|  | 574 | memcpy((void *)((tampon[fib])+off_acheval), (void *)Datas[fib], paqsz-off_acheval); | 
|---|
|  | 575 | curoff = paqsz-off_acheval;  off_acheval = 0; | 
|---|
|  | 576 | if ( MoveToNextTarget() ) { | 
|---|
|  | 577 | cout << "PCIEMultiReader::run()/Error-A- MoveToNextTarget() returned true ->STOP 9" << endl; | 
|---|
|  | 578 | setRC(9);  fgarret=true; break; | 
|---|
|  | 579 | } | 
|---|
|  | 580 | for(uint_4 fib=0; fib<nbDma_; fib++) { | 
|---|
|  | 581 | nextpaq=GetPaquetTarget(fib); | 
|---|
|  | 582 | if (nextpaq == NULL) { // Cela ne devrait pas arriver | 
|---|
|  | 583 | cout << "PCIEReader::run()/Error-A2- GetPaquetTarget(fib)  returned NULL ->STOP 9" << endl; | 
|---|
|  | 584 | setRC(9);  fgarret=true; break; | 
|---|
|  | 585 | } | 
|---|
| [3671] | 586 | // CHECK  S'il faut faire une reduction de taille de paquet | 
|---|
| [3674] | 587 | if (fgredpaq) { // reduction taille de paquet | 
|---|
|  | 588 | if (par_.reducneedcopy) { | 
|---|
|  | 589 | BRPaquet paqc1(tampon[fib], predtampon, paqsz, swapall_); | 
|---|
|  | 590 | BRPaquet paqc2(nextpaq, par_.redpqsize); | 
|---|
|  | 591 | paqc2.CopyFrom(paqc1, par_.pqreducmode, par_.reducoffset); | 
|---|
|  | 592 | } | 
|---|
|  | 593 | else { | 
|---|
|  | 594 | BRPaquet paqc1(tampon[fib], paqsz); | 
|---|
|  | 595 | BRPaquet paqc2(nextpaq, par_.redpqsize); | 
|---|
|  | 596 | paqc2.CopyFrom(paqc1, par_.pqreducmode, par_.reducoffset); | 
|---|
|  | 597 | } | 
|---|
| [3673] | 598 | } | 
|---|
|  | 599 | else  { | 
|---|
|  | 600 | BRPaquet paqc(tampon[fib], nextpaq, paqsz, swapall_); | 
|---|
|  | 601 | } | 
|---|
| [3675] | 602 | BRPaquet paq(nextpaq, packSizeInMgr_); | 
|---|
| [3658] | 603 | npaqfait[fib]++; | 
|---|
|  | 604 | if (fib==nbDma_-1) npaqfaitg++;  // Ne pas oublier le compteur de paquets faits | 
|---|
|  | 605 | pcheck[fib].Check(paq);   // Verification du paquet / FrameCounter | 
|---|
| [3674] | 606 | #ifdef DEBUGPAQHDR | 
|---|
|  | 607 | header[fib] << dec << paq.FrameCounter()<< endl; | 
|---|
|  | 608 | #endif | 
|---|
| [3658] | 609 | } | 
|---|
|  | 610 | } | 
|---|
|  | 611 | else {  // se rapporte au IF numero A | 
|---|
|  | 612 | for(uint_4 fib=0; fib<nbDma_; fib++) | 
|---|
|  | 613 | memcpy((void *)(tampon[fib]+off_acheval), (void *)Datas[fib], dmasz); | 
|---|
|  | 614 | curoff =dmasz; | 
|---|
|  | 615 | off_acheval = (dmasz+off_acheval); | 
|---|
|  | 616 | } | 
|---|
|  | 617 | }  // Fin IF Numero B | 
|---|
|  | 618 |  | 
|---|
|  | 619 | //2- On traite les paquets complets qui se trouvent dans la zone du DMA | 
|---|
|  | 620 | while ((curoff+paqsz)<=dmasz) {  // while numero C | 
|---|
|  | 621 | //          if ((dma==nbDma_-1)&&(npaqfait >= nmax_* memgr.NbPaquets())) break; | 
|---|
|  | 622 | if ( MoveToNextTarget() ) { | 
|---|
|  | 623 | cout << "PCIEMultiReader::run()/Error-B- MoveToNextTarget() returned true ->STOP 9" << endl; | 
|---|
|  | 624 | setRC(9);  fgarret=true; break; | 
|---|
|  | 625 | } | 
|---|
|  | 626 | for(uint_4 fib=0; fib<nbDma_; fib++) { | 
|---|
|  | 627 | if (npaqfait[fib] >= nmax_*memgr.NbPaquets())  continue; | 
|---|
|  | 628 | nextpaq=GetPaquetTarget(fib); | 
|---|
|  | 629 | if (nextpaq == NULL) { // Cela ne devrait pas arriver | 
|---|
|  | 630 | cout << "PCIEReader::run()/Error-B2- GetPaquetTarget(fib)  returned NULL ->STOP 9" << endl; | 
|---|
|  | 631 | setRC(9);  fgarret=true; break; | 
|---|
|  | 632 | } | 
|---|
| [3671] | 633 | // CHECK  S'il faut faire une reduction de taille de paquet | 
|---|
| [3674] | 634 | if (fgredpaq) { // reduction taille de paquet | 
|---|
|  | 635 | if (par_.reducneedcopy) { | 
|---|
|  | 636 | BRPaquet paqc1(Datas[fib]+curoff, predtampon, paqsz, swapall_); | 
|---|
|  | 637 | BRPaquet paqc2(nextpaq, par_.redpqsize); | 
|---|
|  | 638 | paqc2.CopyFrom(paqc1, par_.pqreducmode, par_.reducoffset); | 
|---|
|  | 639 | } | 
|---|
|  | 640 | else { | 
|---|
|  | 641 | BRPaquet paqc1(Datas[fib]+curoff, paqsz); | 
|---|
|  | 642 | BRPaquet paqc2(nextpaq, par_.redpqsize); | 
|---|
|  | 643 | paqc2.CopyFrom(paqc1, par_.pqreducmode, par_.reducoffset); | 
|---|
|  | 644 | } | 
|---|
| [3673] | 645 | } | 
|---|
|  | 646 | else { | 
|---|
|  | 647 | BRPaquet paqc(Datas[fib]+curoff, nextpaq, paqsz, swapall_); | 
|---|
|  | 648 | } | 
|---|
| [3675] | 649 | BRPaquet paq(nextpaq, packSizeInMgr_); | 
|---|
| [3658] | 650 | npaqfait[fib]++; | 
|---|
|  | 651 | if (fib==nbDma_-1) npaqfaitg++;  // Ne pas oublier le compteur de paquets faits | 
|---|
|  | 652 | pcheck[fib].Check(paq);   // Verification du paquet / FrameCounter | 
|---|
| [3674] | 653 | #ifdef DEBUGPAQHDR | 
|---|
|  | 654 | header[fib] << dec << paq.FrameCounter()<< endl; | 
|---|
|  | 655 | #endif | 
|---|
| [3658] | 656 | } | 
|---|
|  | 657 | curoff += paqsz;  // On avance l'index dans le buffer du DMA | 
|---|
|  | 658 | } // -- FIN traitement des paquets complets ds un DMA - FIN du while numero C | 
|---|
|  | 659 | //3- On copie si besoin la fin du DMA dans la zone tampon | 
|---|
|  | 660 | if (curoff < dmasz) {  // IF numero D | 
|---|
|  | 661 | off_acheval = dmasz-curoff; | 
|---|
|  | 662 | for(uint_4 fib=0; fib<nbDma_; fib++) | 
|---|
|  | 663 | memcpy(tampon[fib], (void*)(Datas[fib]+curoff), off_acheval); | 
|---|
|  | 664 | // ne sert a rien         curoff += off_acheval; | 
|---|
|  | 665 | } // FIN du if numero D | 
|---|
|  | 666 | }  //   FIN  Boucle global G | 
|---|
|  | 667 |  | 
|---|
|  | 668 |  | 
|---|
|  | 669 | setRC(0); | 
|---|
|  | 670 | gettimeofday(&tv2, NULL); | 
|---|
|  | 671 | double tmelaps2 = (tv2.tv_sec-tv1.tv_sec)*1000.+(tv2.tv_usec-tv1.tv_usec)/1000.; | 
|---|
|  | 672 | if (tmelaps2<0.1) tmelaps2=0.1; | 
|---|
|  | 673 | cout << " ---------- PCIEMultiReader::run()-End summary NPaqFait=" << npaqfaitg << "------------- " << endl; | 
|---|
|  | 674 | for (int dma=0; dma < (int)nbDma_ ;dma++)   { | 
|---|
|  | 675 | cout << " --Fib=" << dma << " NPaqFait=" << npaqfait[dma] <<  " TotTransfer=" | 
|---|
|  | 676 | << vec_pciw_[dma]->TotTransferBytes()/1024 | 
|---|
|  | 677 | << " kb , ElapsTime=" << tmelaps2 << " ms ->" | 
|---|
|  | 678 | << (double)vec_pciw_[dma]->TotTransferBytes()/tmelaps2 << " kb/s" << endl; | 
|---|
|  | 679 | pcheck[dma].Print(cout); | 
|---|
|  | 680 | } | 
|---|
|  | 681 | cout << " --------------------------------------------------------------------" << endl; | 
|---|
|  | 682 |  | 
|---|
|  | 683 | // //// Nettoyage final | 
|---|
|  | 684 | MZoneManage(true); | 
|---|
| [3674] | 685 | for (int i=0;i< (int)nbDma_ ;i++) delete[] tampon[i]; | 
|---|
|  | 686 | if ((fgredpaq)&&predtampon) delete[] predtampon; | 
|---|
|  | 687 | #ifdef DEBUGPAQHDR | 
|---|
| [3658] | 688 | for(uint_4 fib=0; fib<nbDma_; fib++)  header[fib].close(); | 
|---|
| [3674] | 689 | #endif | 
|---|
|  | 690 |  | 
|---|
| [3658] | 691 | //DBG  cout << " fin thread ========================" <<endl; | 
|---|
|  | 692 | return; | 
|---|
|  | 693 | } | 
|---|
|  | 694 |  | 
|---|
|  | 695 | /* --Methode-- */ | 
|---|
|  | 696 | bool PCIEMultiReader::MZoneManage(bool fgclean)    // Retourne true si probleme | 
|---|
|  | 697 | { | 
|---|
|  | 698 | /* Pour debug | 
|---|
|  | 699 | cout << " PCIEReader::MZoneManage() mid_=" << mid_ << " arg_npaq_= " << targ_npaq_ | 
|---|
|  | 700 | << " max_targ_npaq=" << max_targ_npaq << endl; | 
|---|
|  | 701 | */ | 
|---|
|  | 702 | if (mid_ >= 0)  memgr.FreeMemZone(mid_, MemZS_Filled); | 
|---|
|  | 703 | mmbuf_ = NULL;  targ_npaq_ = 0;  mid_ = -2; | 
|---|
|  | 704 | for (int fid=0;fid<(int)nbDma_ ;fid++) mmbufib_[fid]=NULL; | 
|---|
|  | 705 | if (fgclean)  return false; | 
|---|
|  | 706 | mid_ = memgr.FindMemZoneId(MemZA_Fill); | 
|---|
|  | 707 | mmbuf_ = memgr.GetMemZone(mid_); | 
|---|
|  | 708 | if (mmbuf_==NULL)   return true; | 
|---|
|  | 709 | for (int fid=0;fid<(int)nbDma_ ;fid++) mmbufib_[fid]=memgr.GetMemZone(mid_,fid); | 
|---|
|  | 710 | return false; | 
|---|
|  | 711 | } | 
|---|
|  | 712 |  | 
|---|
|  | 713 | /* | 
|---|
|  | 714 | bool PCIEMultiReader::MZoneManage(int zone,bool fgclean)    // Retourne true si probleme | 
|---|
|  | 715 | { | 
|---|
|  | 716 | // Pour debug | 
|---|
|  | 717 | //cout << " PCIEReader::MZoneManage() mid_=" << mid_ << " arg_npaq_= " << targ_npaq_ | 
|---|
|  | 718 | << " max_targ_npaq=" << max_targ_npaq << endl; | 
|---|
|  | 719 | if (mid_[zone] >= 0)  memgr[zone]->FreeMemZone(mid_[zone], MemZS_Filled); | 
|---|
|  | 720 | mmbuf_[zone] = NULL;  targ_npaq_[zone] = 0;  mid_[zone] = -2; | 
|---|
|  | 721 | if (fgclean)  return false; | 
|---|
|  | 722 | mid_[zone] = memgr[zone]->FindMemZoneId(MemZA_Fill); | 
|---|
|  | 723 | mmbuf_[zone] = memgr[zone]->GetMemZone(mid_[zone]); | 
|---|
|  | 724 | if (mmbuf_[zone]==NULL) return true; | 
|---|
|  | 725 | return false; | 
|---|
|  | 726 | } | 
|---|
|  | 727 | */ | 
|---|
|  | 728 |  | 
|---|
|  | 729 | /* --Methode-- */ | 
|---|
|  | 730 | void PCIEMultiReader::Stop() | 
|---|
|  | 731 | { | 
|---|
|  | 732 | // cout << " PCIEReaderChecker::stop()  ........ STOP" <<endl; | 
|---|
|  | 733 | stop_ = true; | 
|---|
|  | 734 |  | 
|---|
|  | 735 | } | 
|---|
|  | 736 |  | 
|---|
|  | 737 |  | 
|---|
|  | 738 | //-------------------------------------------------------------------- | 
|---|
|  | 739 | // Classe thread de sauvegarde sur fichiers avec gestion multifibres | 
|---|
|  | 740 | //-------------------------------------------------------------------- | 
|---|
|  | 741 |  | 
|---|
| [3672] | 742 | /* --Methode-- */ | 
|---|
|  | 743 | MultiDataSaver::MultiDataSaver(RAcqMemZoneMgr& mem) | 
|---|
| [3671] | 744 | :  memgr(mem) | 
|---|
| [3672] | 745 | { | 
|---|
|  | 746 | BRAcqConfig bpar; | 
|---|
|  | 747 | nfiles_ = bpar.MaxNbFiles(); | 
|---|
|  | 748 | nblocperfile_ = bpar.BlocPerFile(); | 
|---|
| [3658] | 749 | nmax_ = nblocperfile_*nfiles_; | 
|---|
| [3672] | 750 | savesig_ = bpar.GetSaveFits();  // Si false, pas d'ecriture des fichiers FITS du signal | 
|---|
| [3658] | 751 | stop_ = false; | 
|---|
|  | 752 | } | 
|---|
| [3672] | 753 |  | 
|---|
|  | 754 | /* --Methode-- */ | 
|---|
| [3658] | 755 | void MultiDataSaver::Stop() | 
|---|
|  | 756 | { | 
|---|
|  | 757 | // cout<< " MultiDataSaver:Stop ........ " << endl; | 
|---|
|  | 758 | stop_=true; | 
|---|
| [3672] | 759 | } | 
|---|
| [3658] | 760 |  | 
|---|
| [3672] | 761 | /* --Methode-- */ | 
|---|
| [3658] | 762 | void MultiDataSaver::run() | 
|---|
|  | 763 | { | 
|---|
|  | 764 | setRC(1); | 
|---|
|  | 765 | BRPaqChecker pcheck[MAXNBFIB];  // Verification/comptage des paquets | 
|---|
| [3671] | 766 | BRAcqConfig bpar; | 
|---|
| [3658] | 767 | try { | 
|---|
|  | 768 | TimeStamp ts; | 
|---|
|  | 769 | cout << " MultiDataSaver::run() - Starting " << ts << " \n   NbFiles=" << nfiles_ << " NBloc/File=" | 
|---|
|  | 770 | << nblocperfile_ << " NMaxMemZones=" << nmax_ << endl; | 
|---|
|  | 771 | char fname[512]; | 
|---|
|  | 772 |  | 
|---|
| [3672] | 773 | sprintf(fname,"%s/msaver.log",bpar.OutputDirectory().c_str()); | 
|---|
| [3658] | 774 | ofstream filog(fname); | 
|---|
|  | 775 | filog << " MultiDataSaver::run() - starting log file " << ts << " NFibres= " << memgr.NbFibres() << endl; | 
|---|
|  | 776 | filog << " NbFiles=" << nfiles_ << " NBloc/File="  << nblocperfile_ << " NMaxMemZones=" << nmax_ << endl; | 
|---|
|  | 777 |  | 
|---|
|  | 778 | // Fichiers entete ascii et signal FITS | 
|---|
|  | 779 | ofstream header[MAXNBFIB]; | 
|---|
|  | 780 | MiniFITSFile mff[MAXNBFIB]; | 
|---|
|  | 781 |  | 
|---|
|  | 782 | uint_4 fnum=0; | 
|---|
|  | 783 | uint_4 paqsz = memgr.PaqSize(); | 
|---|
|  | 784 | cout << " ============================ MultiDataSaver::run() PaqSize " << paqsz <<endl; | 
|---|
| [3674] | 785 | bool fgfirstfctt=false; | 
|---|
| [3672] | 786 | bool fgnulldev = bpar.GetFileDevNull(); | 
|---|
|  | 787 | if (fgnulldev) { | 
|---|
| [3658] | 788 | cout << " MultiDataSaver::run()/Warning /dev/null path specified, filenames=/dev/null" << endl; | 
|---|
|  | 789 | fgnulldev = true; | 
|---|
|  | 790 | } | 
|---|
| [3671] | 791 | BRPaquet paq0(NULL, NULL, paqsz); | 
|---|
| [3658] | 792 | for (uint_4 nbFile=0;nbFile<nfiles_ ;nbFile++) { | 
|---|
|  | 793 | if (stop_ )   break; | 
|---|
|  | 794 | if (memgr.GetRunState() == MemZR_Stopped) break; | 
|---|
|  | 795 |  | 
|---|
|  | 796 | if (savesig_) | 
|---|
|  | 797 | for(uint_4 fib=0; fib<memgr.NbFibres(); fib++) { | 
|---|
|  | 798 | if (fgnulldev) strcpy(fname,"/dev/null"); | 
|---|
| [3672] | 799 | else sprintf(fname,"%sHDRfits%d.txt",bpar.OutputDirectoryFib(fib).c_str(),fnum); | 
|---|
| [3658] | 800 | header[fib].open(fname); | 
|---|
|  | 801 | } | 
|---|
| [3671] | 802 |  | 
|---|
| [3658] | 803 | uint_4 npaqperfile = memgr.NbPaquets()*nblocperfile_;  // Nombre de paquets ecrits dans un fichier | 
|---|
|  | 804 |  | 
|---|
|  | 805 | if (savesig_) { //Reza - Ouverture conditionnel fichier | 
|---|
| [3671] | 806 | for(uint_4 fib=0; fib<memgr.NbFibres(); fib++)    { | 
|---|
| [3658] | 807 | if (fgnulldev) strcpy(fname,"/dev/null"); | 
|---|
| [3672] | 808 | else sprintf(fname,"%ssignal%d.fits",bpar.OutputDirectoryFib(fib).c_str(),(int)fnum); | 
|---|
|  | 809 | //      cout << " ***DBG** Opening file " << fname << endl; | 
|---|
| [3658] | 810 | mff[fib].Open(fname,MF_Write);  //Reza - Ouverture conditionnel fichier | 
|---|
|  | 811 | // Entete correspondant a l'ecriture tout le paquet - trailer compris (modif Mai 2009) | 
|---|
| [3671] | 812 | mff[fib].setDTypeNaxis(MF_Byte, paq0.PaquetSize(), npaqperfile); | 
|---|
|  | 813 | // Sans TRAILER de paquet mff.setDTypeNaxis(MF_Byte, paq0.DataSize()+paq0.HeaderSize(), npaqperfile); | 
|---|
| [3658] | 814 | } | 
|---|
| [3683] | 815 | AddFitsKWStart(mff,bpar); | 
|---|
| [3674] | 816 | fnum++;   fgfirstfctt=true; | 
|---|
| [3658] | 817 | } | 
|---|
|  | 818 | else sprintf(fname,"MemDataBloc[%d]-NoDataFile",(int)fnum++); | 
|---|
|  | 819 |  | 
|---|
|  | 820 | for (uint_4 kmz=0; kmz<nblocperfile_; kmz++) { | 
|---|
|  | 821 | if (stop_) break; | 
|---|
|  | 822 | //DBG cout << " MultiDataSaver::run()- nbFile=" << nbFile << " kmz=" << kmz << endl; | 
|---|
|  | 823 | int mid = memgr.FindMemZoneId(MemZA_Save); | 
|---|
|  | 824 | Byte* buffg = memgr.GetMemZone(mid); | 
|---|
|  | 825 | if (buffg == NULL) { | 
|---|
|  | 826 | cout << " MultiDataSaver::run()/ERROR memgr.GetMemZone(" << mid << ") -> NULL" << endl; | 
|---|
| [3671] | 827 | setRC(21); | 
|---|
| [3658] | 828 | return; | 
|---|
|  | 829 | } | 
|---|
|  | 830 | for(uint_4 fib=0; fib<memgr.NbFibres(); fib++)  {  // Boucle sur les fibres | 
|---|
|  | 831 | Byte* buff = memgr.GetMemZone(mid,fib); | 
|---|
|  | 832 | if (buff == NULL) {  // Ceci ne devrait pas arriver - suite au test buffg ci-dessus | 
|---|
|  | 833 | cout << " MultiDataSaver::run()/ERROR memgr.GetMemZone(" << mid << "," << fib << ") -> NULL" << endl; | 
|---|
| [3671] | 834 | setRC(22); | 
|---|
| [3658] | 835 | return; | 
|---|
|  | 836 | } | 
|---|
|  | 837 | for(uint_4 i=0; i<memgr.NbPaquets(); i++) {  // boucle sur les paquets | 
|---|
|  | 838 | BRPaquet paq(NULL, buff+i*paqsz, paqsz); | 
|---|
| [3674] | 839 | bool cpaqok=pcheck[fib].Check(paq);   // Verification du paquet / FrameCounter | 
|---|
|  | 840 | if (cpaqok && fgfirstfctt) { | 
|---|
|  | 841 | framecnt_first_[fib] = pcheck[fib].LastFrameNum(); | 
|---|
|  | 842 | timetag_first_[fib] = paq.TimeTag(); | 
|---|
|  | 843 | fgfirstfctt=false; | 
|---|
|  | 844 | } | 
|---|
| [3658] | 845 | if (savesig_) | 
|---|
|  | 846 | header[fib] << hex << paq.HDRMarker() << " " << paq.TRLMarker() << " " | 
|---|
|  | 847 | << paq.TimeTag2()<< " "<< paq.TimeTag1()<< " " | 
|---|
|  | 848 | << paq.FrameCounter() << " " << paq.PaqLen()  << endl; | 
|---|
|  | 849 | if (savesig_) // Reza - Ecriture conditionnel fichier fits signal | 
|---|
|  | 850 | mff[fib].WriteB(paq.Header(),paq.PaquetSize()); // ecriture tout le paquet (modif Mai 2009) | 
|---|
|  | 851 | } // Fin de la boucle sur les paquets | 
|---|
|  | 852 | }  // Fin de la boucle sur les fibres | 
|---|
|  | 853 | memgr.FreeMemZone(mid, MemZS_Saved); | 
|---|
|  | 854 | }  // Boucle sur les blocs dans un meme fichier | 
|---|
|  | 855 | ts.SetNow(); | 
|---|
|  | 856 | filog << ts << " : OK data files " << endl; | 
|---|
|  | 857 | cout << " MultiDataSaver::run() " << ts << " : OK data files  " << endl; | 
|---|
|  | 858 | for(uint_4 fib=0; fib<memgr.NbFibres(); fib++) { | 
|---|
|  | 859 | if (savesig_) { | 
|---|
|  | 860 | if (fgnulldev) strcpy(fname,"/dev/null"); | 
|---|
| [3672] | 861 | else sprintf(fname,"%ssignal%d.fits",bpar.OutputDirectoryFib(fib).c_str(),(int)fnum); | 
|---|
| [3658] | 862 | } | 
|---|
|  | 863 | else sprintf(fname,"MemDataBloc[%d]-NoDataFile",(int)fnum-1); | 
|---|
| [3671] | 864 | string pcsum = pcheck[fib].Summary(); | 
|---|
|  | 865 | filog << "    Fib " << fib << " -> " << fname << " Stat:" << pcsum << endl; | 
|---|
|  | 866 | cout  << "    Fib " << fib << " -> " << fname << " Stat:" << pcsum << endl; | 
|---|
| [3658] | 867 | } | 
|---|
| [3674] | 868 | if (savesig_)  { | 
|---|
|  | 869 | // Ajout mots-cle additionnels a tous les fichiers FITS | 
|---|
|  | 870 | for(uint_4 fib=0; fib<memgr.NbFibres(); fib++) | 
|---|
|  | 871 | framecnt_last_[fib] = pcheck[fib].LastFrameNum(); | 
|---|
|  | 872 |  | 
|---|
| [3683] | 873 | AddFitsKWEnd(mff,bpar); | 
|---|
| [3658] | 874 | for(uint_4 fib=0; fib<memgr.NbFibres(); fib++) { | 
|---|
|  | 875 | header[fib].close(); | 
|---|
|  | 876 | mff[fib].Close(); | 
|---|
|  | 877 | } | 
|---|
| [3674] | 878 | } | 
|---|
| [3671] | 879 |  | 
|---|
| [3658] | 880 | }  // Fin de boucle sur les fichiers | 
|---|
|  | 881 | cout << " --------------------  MultiDataSaver::run() -------------------- " << endl; | 
|---|
|  | 882 | for(uint_4 fib=0; fib<memgr.NbFibres(); fib++) { | 
|---|
|  | 883 | cout << " MultiDataSaver/Summary Fib " << fib << endl; | 
|---|
|  | 884 | pcheck[fib].Print(cout); | 
|---|
|  | 885 | filog << " MultiDataSaver/Summary Fib " << fib << endl; | 
|---|
|  | 886 | pcheck[fib].Print(filog); | 
|---|
|  | 887 | } | 
|---|
|  | 888 | cout << " ---------------------------------------------------------- " << endl; | 
|---|
|  | 889 | ts.SetNow(); | 
|---|
|  | 890 | filog << " MultiDataSaver::run() - End of processing/run() " << ts << endl; | 
|---|
|  | 891 |  | 
|---|
|  | 892 | } | 
|---|
|  | 893 | catch (MiniFITSException& exc) { | 
|---|
|  | 894 | cout << " MultiDataSaver::run()/catched MiniFITSException " << exc.Msg() << endl; | 
|---|
|  | 895 | setRC(3); | 
|---|
|  | 896 | return; | 
|---|
|  | 897 | } | 
|---|
|  | 898 | catch(...) { | 
|---|
|  | 899 | cout << " MultiDataSaver::run()/catched unknown ... exception " << endl; | 
|---|
|  | 900 | setRC(4); | 
|---|
|  | 901 | return; | 
|---|
|  | 902 | } | 
|---|
|  | 903 | setRC(0); | 
|---|
|  | 904 | return; | 
|---|
|  | 905 | } | 
|---|
|  | 906 |  | 
|---|
| [3671] | 907 |  | 
|---|
|  | 908 | /* --Methode-- */ | 
|---|
| [3683] | 909 | int MultiDataSaver::AddFitsKWStart(MiniFITSFile* mff, BRAcqConfig& acpar) | 
|---|
| [3671] | 910 | { | 
|---|
|  | 911 | TimeStamp ts; | 
|---|
|  | 912 | string cdtu=ts.ToString(); | 
|---|
| [3674] | 913 | string& skysrc=acpar.SkySource(); | 
|---|
|  | 914 | bool hassrc=false; | 
|---|
|  | 915 | if (skysrc.length()>0)  hassrc=true; | 
|---|
| [3683] | 916 | bool fgredpsz = acpar.GetParams().fgreducpsize; | 
|---|
| [3671] | 917 | for(uint_4 fib=0; fib<memgr.NbFibres(); fib++) { | 
|---|
|  | 918 | mff[fib].AddKeyS("DATEOBS", cdtu.c_str(), " Observation Time (YYYY-MM-DDThh:mm:ss UT) "); | 
|---|
| [3683] | 919 | mff[fib].AddKeyS("TMSTART", cdtu.c_str(), " File Acqu. Start Time/Date  "); | 
|---|
| [3671] | 920 | mff[fib].AddKeyD("ACQVER", acpar.AcqVersion(), " BAORadio Acq Software version ") ; | 
|---|
| [3677] | 921 | mff[fib].AddKeyS("ACQMODE", acpar.GetParams().AcqMode, " BAORadio Acq run  mode" ); | 
|---|
| [3683] | 922 | mff[fib].AddKeyS("BRPAQCFMT", BRPaquet::FmtConvToString(acpar.GetParams().GetDataConvFg()), | 
|---|
|  | 923 | " BAORadio BRPaquet DataFormatConversion" ); | 
|---|
| [3675] | 924 | mff[fib].AddKeyI("FIBERNUM", acpar.GetParams().FiberNum[fib], " Fiber number/id") ; | 
|---|
| [3674] | 925 | if (hassrc) | 
|---|
|  | 926 | mff[fib].AddKeyS("SKYSOURC", skysrc, " Source identification" ); | 
|---|
| [3683] | 927 | if (fgredpsz) { | 
|---|
|  | 928 | mff[fib].AddKeyS("REDPSZMOD", BRPaquet::ReducActionToString(acpar.GetParams().pqreducmode), | 
|---|
|  | 929 | "PaquetSize Reduction Mode") ; | 
|---|
|  | 930 | mff[fib].AddKeyI("REDPSZOF", acpar.GetParams().reducoffset," PaquetSize Reduction Offset") ; | 
|---|
|  | 931 | } | 
|---|
|  | 932 | } | 
|---|
|  | 933 | return 0; | 
|---|
|  | 934 | } | 
|---|
|  | 935 |  | 
|---|
|  | 936 | /* --Methode-- */ | 
|---|
|  | 937 | int MultiDataSaver::AddFitsKWEnd(MiniFITSFile* mff, BRAcqConfig& acpar) | 
|---|
|  | 938 | { | 
|---|
|  | 939 | TimeStamp ts; | 
|---|
|  | 940 | string cdtu=ts.ToString(); | 
|---|
|  | 941 | for(uint_4 fib=0; fib<memgr.NbFibres(); fib++) { | 
|---|
|  | 942 | mff[fib].AddKeyS("TMEND", cdtu.c_str(), " File Acqu. End Time/Date  "); | 
|---|
| [3674] | 943 | mff[fib].AddKeyI("FCFIRST", framecnt_first_[fib], " First valid frame counter in file") ; | 
|---|
|  | 944 | mff[fib].AddKeyI("FCLAST", framecnt_last_[fib], " Last valid frame counter in file") ; | 
|---|
|  | 945 | mff[fib].AddKeyI("TTFIRST", timetag_first_[fib], " First valid timetag in file") ; | 
|---|
| [3671] | 946 | } | 
|---|
|  | 947 | return 0; | 
|---|
|  | 948 | } | 
|---|
|  | 949 |  | 
|---|