00001
00034 #ifndef __QCRATERECEIVERBUFFER_HH_
00035 #define __QCRATERECEIVERBUFFER_HH_
00036
00037 #include <string>
00038 #include <vector>
00039 #include <stdexcept>
00040 #include <unistd.h>
00041 #include <iostream>
00042 #include <zlib.h>
00043 #include <math.h>
00044
00045 #include "QCuore.hh"
00046 #include "QError.hh"
00047 #include "QConnectedSocket.hh"
00048
00049 #define DEFAULT_BUFFER_SIZE 60000
00050 #define MAX_CHANNEL_FILE_SIZE 20000000
00070 struct QBufferStructure_t {
00071 unsigned long fId;
00072 unsigned long fNum;
00073 unsigned long long fRead;
00074 unsigned long long fWrite;
00075 unsigned long long fReadFile;
00076 unsigned long long fNotProcessed;
00078 unsigned long long fNotBuilt;
00080 unsigned long fCurrentRun;
00081 bool fNotProcessedIsActive;
00083 bool fReadPtrIsActive;
00085 bool fNotBuiltIsActive;
00087 bool fSaveFile;
00089 unsigned long fSamplingRate;
00091 long fData[DEFAULT_BUFFER_SIZE];
00092 };
00093
00094
00095 class QCrateReceiverBuffer {
00096 public:
00097 QCrateReceiverBuffer(unsigned long ch,
00098 bool attach,
00099 bool OpenFiles,
00100 int RunNumber=0,
00101 bool offset_shm=false);
00102
00103 virtual ~QCrateReceiverBuffer();
00104
00105 unsigned long Size() const {return DEFAULT_BUFFER_SIZE;}
00106
00108 char* Start() const
00109 {return
00110 (char*)(&(p_buffer->fData[(p_buffer->fRead) % DEFAULT_BUFFER_SIZE]));}
00111
00113 inline unsigned long GetNumberOfWords() const
00114 {return p_buffer->fNum;}
00115
00124 bool EnableTriggerPointer();
00125
00127 void ReleaseTriggerPointer();
00128
00137 bool EnableBuilderPointer();
00138
00140 void ReleaseBuilderPointer();
00141
00150 bool EnableReadPointer();
00151
00153 void ReleaseReadPointer();
00154
00160 inline void Release(unsigned int n);
00161
00167 void Add(int n, const long* data);
00168
00172 void AddFromNetwork(QConnectedSocket* cs);
00173
00175 inline int GetLg() const {return p_buffer->fId;}
00176
00178 inline int ReadToEnd() const
00179 {return DEFAULT_BUFFER_SIZE -
00180 (unsigned long)((p_buffer->fRead) % DEFAULT_BUFFER_SIZE);}
00181
00183 inline void SetProcessed(unsigned int n);
00184
00186 inline void SetBuilt(unsigned int n);
00187
00188
00189 inline unsigned long GetToBeProcessed() const
00190 {return (unsigned long)(p_buffer->fWrite - p_buffer->fNotProcessed);}
00191
00193 inline unsigned long GetToBeBuilt() const
00194 {return (unsigned long)(p_buffer->fNotProcessed - p_buffer->fNotBuilt);}
00195
00197 inline unsigned long GetToBeRead() const
00198 {return (unsigned long)(p_buffer->fReadFile - p_buffer->fRead);}
00199
00201 inline unsigned long long GetProcessed() const
00202 {return p_buffer->fNotProcessed;}
00203
00205 inline unsigned long long GetBuilt() const
00206 {return p_buffer->fNotBuilt;}
00207
00209 inline unsigned long long GetRead() const
00210 {return p_buffer->fRead;}
00211
00213 inline unsigned long long GetWritten() const
00214 {return p_buffer->fWrite;}
00215
00227 inline long GetData(unsigned long long index) const;
00228
00238 inline long GetSample(unsigned long long index) const;
00239
00247 inline short GetTriggerFlags(unsigned long long index, unsigned long mask=0xF) const
00248 {return (short)((GetData(index) >> 17) & mask);}
00249
00255 inline void FlagTrigger(unsigned long long index,
00256 int tag);
00257
00265 inline void SetTriggerEnabled(bool enabled);
00266
00268 void SetSamplingRate(unsigned long rate) {p_buffer->fSamplingRate = rate;}
00269
00271 unsigned long GetSamplingRate() const
00272 {return p_buffer->fSamplingRate;}
00273
00281 inline long long GetTimeOfSample(unsigned long long index) const;
00282
00284 inline unsigned long long GetSampleOfTime(long long time) const;
00285
00286
00287 void Dump();
00288
00289
00290
00291
00292
00293
00294
00295 inline void SetScanned(unsigned long long i)
00296 {p_buffer->fData[(i % DEFAULT_BUFFER_SIZE)] |= (1<<27);}
00297
00298 inline void SetAnalyzed(unsigned long long i)
00299 {p_buffer->fData[(i % DEFAULT_BUFFER_SIZE)] |= (1<<28);}
00300
00301 private:
00302 inline void Release();
00303
00308 inline void SetProcessed();
00309
00314 inline void SetBuilt();
00315
00317 inline unsigned long GetToBeWritten() const
00318 {return (unsigned long)(p_buffer->fNotBuilt - p_buffer->fReadFile);}
00319
00321 void WriteFile();
00322
00324 void OpenFile();
00325
00327 void CloseFile(bool last);
00328
00329 int fHandle;
00330 int fShmid;
00331 bool fOwn;
00333 QBufferStructure_t *p_buffer;
00334 gzFile zFile;
00335 std::string fGzFileName;
00336 unsigned int fPartialFile;
00337 bool fReadPtrBooked;
00339 bool fBuilderPtrBooked;
00342 bool fTrgPtrBooked;
00345 };
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357 inline void QCrateReceiverBuffer::SetProcessed()
00358 {
00359 p_buffer->fNotProcessed = p_buffer->fWrite;
00360
00361
00362 if(!p_buffer->fNotBuiltIsActive) SetBuilt();
00363 }
00364
00365
00366
00367 inline void QCrateReceiverBuffer::SetProcessed(unsigned int n)
00368 {
00369
00370
00371 if(!fTrgPtrBooked) {
00372 std::cerr << "QCrateReceiverBuffer::SetProcessed(unsigned int) Warning! "
00373 "trying to move \"trigger pointer\" without having permission!!"
00374 << std::endl;
00375 return;
00376 }
00377
00378
00379 if(n > GetToBeProcessed()) {
00380 n = GetToBeProcessed();
00381 std::cerr << "QCrateReceiverBuffer::SetProcessed Warning! moving "
00382 "\"Processed by trigger\" pointer into an inconsistent position "
00383 "avoided!" << std::endl;
00384 }
00385
00386
00387 p_buffer->fNotProcessed+=n;
00388
00389
00390 if(!p_buffer->fNotBuiltIsActive) SetBuilt();
00391 }
00392
00393
00394
00395 inline void QCrateReceiverBuffer::SetBuilt()
00396 {
00397 p_buffer->fNotBuilt = p_buffer->fNotProcessed;
00398
00399
00400 if(!p_buffer->fReadPtrIsActive) Release();
00401 }
00402
00403
00404
00405 inline void QCrateReceiverBuffer::SetBuilt(unsigned int n)
00406 {
00407
00408
00409 if(!fBuilderPtrBooked) {
00410 std::cerr << "QCrateReceiverBuffer::SetBuilt(unsigned int) Warning! "
00411 "trying to move \"builder pointer\" without having permission!!"
00412 << std::endl;
00413 return;
00414 }
00415
00416
00417 if(n > GetToBeBuilt()) {
00418 n = GetToBeBuilt();
00419 std::cerr << "QCrateReceiverBuffer::SetBuilt Warning! moving "
00420 "\"Processed by Builder\" pointer into an inconsistent position "
00421 "avoided!" << std::endl;
00422 }
00423
00424
00425 p_buffer->fNotBuilt+=n;
00426
00427
00428 if(!p_buffer->fReadPtrIsActive) Release();
00429 }
00430
00431
00432
00433 inline void QCrateReceiverBuffer::Release()
00434 {
00435
00436 p_buffer->fNum -= GetToBeRead();
00437
00438
00439 p_buffer->fRead += GetToBeRead();
00440 }
00441
00442
00443
00444 inline void QCrateReceiverBuffer::Release(unsigned int n)
00445 {
00446
00447 if(!fReadPtrBooked) {
00448 std::cerr << "QCrateReceiverBuffer::Release(unsigned int) Warning: "
00449 "trying to move read pointer without having permission." << std::endl;
00450 return;
00451 }
00452
00453
00454 if(n > GetToBeRead())
00455 {
00456 std::cerr << "QCrateReceiverBuffer::Release Warning! avoided "
00457 "inconsistent moving of \"read\" pointer for channel "
00458 << p_buffer->fId << ". requested: " << n
00459 << ", allowed: " << GetToBeRead() << std::endl;
00460 n = GetToBeRead();
00461 }
00462
00463
00464 p_buffer->fRead += n;
00465
00466
00467 p_buffer->fNum -= n;
00468 }
00469
00470
00471
00472
00473 inline void QCrateReceiverBuffer::FlagTrigger(unsigned long long index,
00474 int tag)
00475 {
00476 if(index < p_buffer->fRead || index > p_buffer->fWrite)
00477 {
00478 QError err(QERR_SHMEM_INVALID_INDEX);
00479 err.SetDescription("In FlagTrigger(): index out of bounds");
00480 throw err;
00481 }
00482
00483 int position = 16+tag;
00484 unsigned long circularIndex = (unsigned long)(index % DEFAULT_BUFFER_SIZE);
00485 p_buffer->fData[circularIndex] |= (1 << position);
00486
00487 }
00488
00489
00490
00491
00492
00493
00494 inline long long QCrateReceiverBuffer::GetTimeOfSample(unsigned long long index)
00495 const
00496 {
00497 const unsigned long s2Ns = 1000000000;
00498 long long time = (s2Ns * index / p_buffer->fSamplingRate);
00499 if(index < p_buffer->fRead || index > p_buffer->fWrite) time *= -1;
00500 return time;
00501 }
00502
00503
00504
00505 inline unsigned long long QCrateReceiverBuffer::GetSampleOfTime(long long time)
00506 const
00507 {
00508
00509 if(time < 0) return 0;
00510 const unsigned long s2Ns = 1000000000;
00511 return (unsigned long long)(time * p_buffer->fSamplingRate / s2Ns);
00512 }
00513
00514
00515 inline long QCrateReceiverBuffer::GetData(unsigned long long index) const
00516 {
00517 unsigned long long lastValid = ((p_buffer->fWrite)>DEFAULT_BUFFER_SIZE)?
00518 (p_buffer->fWrite)-DEFAULT_BUFFER_SIZE:0;
00519 if(index < lastValid || index > p_buffer->fWrite)
00520 {
00521 QError err(QERR_SHMEM_INVALID_INDEX);
00522 char errMsg[300];
00523 sprintf(errMsg,"In GetData(): requested buffer index (%lld) is out of "
00524 "bounds (%lld - %lld)", index, lastValid, p_buffer->fWrite);
00525 err.SetDescription(errMsg);
00526 throw err;
00527 }
00528 unsigned long circular_index=(unsigned long)(index % DEFAULT_BUFFER_SIZE);
00529 return p_buffer->fData[circular_index];
00530 }
00531
00532
00533 inline long QCrateReceiverBuffer::GetSample(unsigned long long index) const
00534 {
00535 const long dataMask = 0x8001FFFF;
00536 long sample = GetData(index) & dataMask;
00537
00538 if(sample >> 31) sample |= 0x7FFE0000;
00539
00540 return sample;
00541 }
00542
00543
00544
00545 inline void QCrateReceiverBuffer::SetTriggerEnabled(bool enabled)
00546 {
00547
00548 int position = 25;
00549 if(enabled) position++;
00550
00551
00552 p_buffer->fData[(p_buffer->fWrite % DEFAULT_BUFFER_SIZE) - 1] |=
00553 1L << position;
00554
00555 return;
00556 }
00557
00558 #endif