Skip to content

Commit 9ec1ef6

Browse files
authored
Merge pull request #224 from sy-c/master
v2.11
2 parents a67c11c + 4911695 commit 9ec1ef6

16 files changed

+253
-16
lines changed

doc/configurationParameters.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ The parameters related to 3rd-party libraries are described here for convenience
6969
| consumer-fileRecorder-* | fileName | string | | Path to the file where to record data. The following variables are replaced at runtime: ${XXX} -> get variable XXX from environment, %t -> unix timestamp (seconds since epoch), %T -> formatted date/time, %i -> equipment ID of each data chunk (used to write data from different equipments to different output files), %l -> link ID (used to write data from different links to different output files). |
7070
| consumer-fileRecorder-* | filesMax | int | 1 | If 1 (default), file splitting is disabled: file is closed whenever a limit is reached on a given recording stream. Otherwise, file splitting is enabled: whenever the current file reaches a limit, it is closed an new one is created (with an incremental name). If <=0, an unlimited number of incremental chunks can be created. If non-zero, it defines the maximum number of chunks. The file name is suffixed with chunk number (by default, ".001, .002, ..." at the end of the file name. One may use "%f" in the file name to define where this incremental file counter is printed. |
7171
| consumer-fileRecorder-* | pagesMax | int | 0 | Maximum number of data pages accepted by recorder. If zero (default), no maximum set.|
72+
| consumer-fileRecorder-* | tfMax | int | 0 | Maximum number of timeframes accepted by recorder. If zero (default), no maximum set.|
7273
| consumer-processor-* | ensurePageOrder | int | 0 | If set, ensures that data pages goes out of the processing pool in same order as input (which is not guaranteed with multithreading otherwise). This option adds latency. |
7374
| consumer-processor-* | libraryPath | string | | Path to the library file providing the processBlock() function to be used. |
7475
| consumer-processor-* | numberOfThreads | int | 1 | Number of threads running the processBlock() function in parallel. |
@@ -91,6 +92,7 @@ The parameters related to 3rd-party libraries are described here for convenience
9192
| consumer-zmq-* | zmqOptions | string | | Additional ZMQ options, as a comma-separated list of key=value pairs. Possible keys: ZMQ_CONFLATE, ZMQ_IO_THREADS, ZMQ_LINGER, ZMQ_SNDBUF, ZMQ_SNDHWM, ZMQ_SNDTIMEO. |
9293
| equipment-* | blockAlign | bytes | 2M | Alignment of the beginning of the big memory block from which the pool is created. Pool will start at a multiple of this value. Each page will then begin at a multiple of memoryPoolPageSize from the beginning of big block. |
9394
| equipment-* | consoleStatsUpdateTime | double | 0 | If set, number of seconds between printing statistics on console. |
95+
| equipment-* | ctpMode | int | 0 | If set, the detector field (CTP run mask) is checked. Incoming data is discarded until a new bit is set, and discarded again after this bit is unset. Automatically implies rdhCheckDetectorField=1 and rdhCheckDetectorField=1. |
9496
| equipment-* | dataPagesLogPath | string | | Path where to save a summary of each data pages generated by equipment. |
9597
| equipment-* | debugFirstPages | int | 0 | If set, print debug information for first (given number of) data pages readout. |
9698
| equipment-* | disableOutput | int | 0 | If non-zero, data generated by this equipment is discarded immediately and is not pushed to output fifo of readout thread. Used for testing. |
@@ -116,6 +118,7 @@ The parameters related to 3rd-party libraries are described here for convenience
116118
| equipment-* | saveErrorPagesPath | string | | Path where to save data pages with errors (when feature enabled). |
117119
| equipment-* | stopOnError | int | 0 | If 1, readout will stop automatically on equipment error. |
118120
| equipment-* | TFperiod | int | 128 | Duration of a timeframe, in number of LHC orbits. |
121+
| equipment-* | verbose | int | 0 | If set, extra debug messages may be logged. |
119122
| equipment-cruemulator-* | cruBlockSize | int | 8192 | Size of a RDH block. |
120123
| equipment-cruemulator-* | cruId | int | 0 | CRU Id, used for CRU Id field in RDH. |
121124
| equipment-cruemulator-* | dpwId | int | 0 | CRU end-point Id (data path wrapper id), used for DPW Id field in RDH. |

doc/releaseNotes.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,3 +460,11 @@ This file describes the main feature changes for each readout.exe released versi
460460

461461
## v2.10.4 - 18/05/2022
462462
- Changed level of "Bypassing RORC firmware compatibility check", retrograded from support warning to developper info.
463+
464+
## v2.11 - 15/06/2022
465+
- Added orbit counter to stats.
466+
- Updated configuration parameters:
467+
- equipment-*.verbose: adds some extra verbosity.
468+
- equipment-*.ctpMode: enables CTP mode, data is discarded until start of run detected in RDH detector field pattern, and after corresponding end of run is detected.
469+
- consumer-fileRecorder-*.tfMax: when set, recording will stop after reaching given number of timeframes.
470+
- o2-readout-rawreader: added option to dump stats on HBF size.

src/ConsumerFileRecorder.cxx

Lines changed: 41 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,15 @@
2121
class FileHandle
2222
{
2323
public:
24-
FileHandle(std::string& _path, InfoLogger* _theLog = nullptr, unsigned long long _maxFileSize = 0, int _maxPages = 0)
24+
FileHandle(std::string& _path, InfoLogger* _theLog = nullptr, unsigned long long _maxFileSize = 0, int _maxPages = 0, int _maxTF = 0)
2525
{
2626
theLog = _theLog;
2727
path = _path;
2828
counterBytesTotal = 0;
2929
maxFileSize = _maxFileSize;
3030
maxPages = _maxPages;
31+
maxTF = _maxTF;
32+
3133
if (theLog != nullptr) {
3234
theLog->log(LogInfoDevel_(3007), "Opening file for writing: %s", path.c_str());
3335
}
@@ -62,7 +64,7 @@ class FileHandle
6264
enum Status { Success = 0,
6365
Error = -1,
6466
FileLimitsReached = 1 };
65-
FileHandle::Status write(void* ptr, size_t size, bool isPage = false, size_t remainingBlockSize = 0)
67+
FileHandle::Status write(void* ptr, size_t size, uint64_t TFid, bool isPage = false, size_t remainingBlockSize = 0)
6668
{
6769
lastWriteBytes = 0; // reset last bytes written
6870
if (isFull) {
@@ -88,6 +90,20 @@ class FileHandle
8890
close();
8991
return Status::FileLimitsReached;
9092
}
93+
if (TFid != undefinedTimeframeId) {
94+
if (TFid != lastTFid) {
95+
lastTFid = TFid;
96+
counterTF++;
97+
}
98+
}
99+
if ((maxTF) && (counterTF > maxTF)) {
100+
if (theLog != nullptr) {
101+
theLog->log(LogInfoDevel_(3007), "Maximum number of TF in file reached");
102+
}
103+
isFull = true;
104+
close();
105+
return Status::FileLimitsReached;
106+
}
91107
if (fp == NULL) {
92108
return Status::Error;
93109
}
@@ -113,6 +129,10 @@ class FileHandle
113129
unsigned long long maxFileSize = 0; // max number of bytes to write to file (0=no limit)
114130
int counterPages = 0; // number of pages received so far
115131
int maxPages = 0; // max number of pages accepted by recorder (0=no limit)
132+
uint64_t lastTFid = undefinedTimeframeId; // id of last TF written
133+
int counterTF = 0; // number of TF received so far
134+
int maxTF = 0; // max number of timeframes accepted by recorder (0=no limit)
135+
116136
FILE* fp = NULL; // handle to file for I/O
117137
InfoLogger* theLog = nullptr; // handle to infoLogger for messages
118138
bool isFull = false; // flag set when maximum file size reached
@@ -165,6 +185,14 @@ class ConsumerFileRecorder : public Consumer
165185
}
166186
}
167187

188+
// configuration parameter: | consumer-fileRecorder-* | tfMax | int | 0 | Maximum number of timeframes accepted by recorder. If zero (default), no maximum set.|
189+
maxFileTF = 0;
190+
if (cfg.getOptionalValue<int>(cfgEntryPoint + ".tfMax", maxFileTF) == 0) {
191+
if (maxFileTF) {
192+
theLog.log(LogInfoDevel_(3002), "Maximum recording size: %d timeframes", maxFileTF);
193+
}
194+
}
195+
168196
// configuration parameter: | consumer-fileRecorder-* | dataBlockHeaderEnabled | int | 0 | Enable (1) or disable (0) the writing to file of the internal readout header (Readout DataBlock.h) between the data pages, to easily navigate through the file without RDH decoding. If disabled, the raw data pages received from CRU are written without further formatting. |
169197
cfg.getOptionalValue(cfgEntryPoint + ".dataBlockHeaderEnabled", recordWithDataBlockHeader, 0);
170198
theLog.log(LogInfoDevel_(3002), "Recording internal data block headers = %d", recordWithDataBlockHeader);
@@ -366,7 +394,7 @@ class ConsumerFileRecorder : public Consumer
366394
}
367395

368396
// create file handle
369-
std::shared_ptr<FileHandle> newHandle = std::make_shared<FileHandle>(newFileName, &theLog, maxFileSize, maxFilePages);
397+
std::shared_ptr<FileHandle> newHandle = std::make_shared<FileHandle>(newFileName, &theLog, maxFileSize, maxFilePages, maxFileTF);
370398
if (newHandle == nullptr) {
371399
return -1;
372400
}
@@ -429,7 +457,7 @@ class ConsumerFileRecorder : public Consumer
429457

430458
bool countPage = true; // the first write will increment the page counter for this file
431459

432-
auto writeToFile = [&](void* ptr, size_t size, size_t remainingBlockSize) {
460+
auto writeToFile = [&](void* ptr, size_t size, uint64_t TFid, size_t remainingBlockSize) {
433461
// two attempts, in case file needs to be incremented
434462
for (int i = 0; i < 2; i++) {
435463

@@ -440,7 +468,7 @@ class ConsumerFileRecorder : public Consumer
440468
}
441469

442470
// try to write
443-
FileHandle::Status status = fpUsed->write(ptr, size, countPage, remainingBlockSize);
471+
FileHandle::Status status = fpUsed->write(ptr, size, TFid, countPage, remainingBlockSize);
444472

445473
// check if need to move to next file
446474
if (status == FileHandle::Status::FileLimitsReached) {
@@ -504,14 +532,14 @@ class ConsumerFileRecorder : public Consumer
504532
// as-is, some fields like data pointer will not be meaningful in file unless corrected.
505533
// todo: correct them, e.g. replace data pointer by file offset.
506534
// In particular, incompatible with dropEmptyHBFrames as size changes.
507-
writeToFile(&b->getData()->header, (size_t)b->getData()->header.headerSize, (size_t)b->getData()->header.dataSize);
535+
writeToFile(&b->getData()->header, (size_t)b->getData()->header.headerSize, b->getData()->header.timeframeId, (size_t)b->getData()->header.dataSize);
508536
// datablock header does not count as a page, but we account for the payload size for the next write (possibly one full page)
509537
}
510538

511539
// write payload data
512540
if (!dropEmptyHBFrames) {
513541
// by default, we write the full payload data
514-
writeToFile(b->getData()->data, (size_t)b->getData()->header.dataSize, 0);
542+
writeToFile(b->getData()->data, (size_t)b->getData()->header.dataSize, b->getData()->header.timeframeId, 0);
515543
} else {
516544
// we have to check packet by packet and discard empty HBstart/HBstop pairs
517545
size_t blockSize = b->getData()->header.dataSize;
@@ -545,7 +573,7 @@ class ConsumerFileRecorder : public Consumer
545573

546574
// write previous packet
547575
if (previousPacket.address != nullptr) {
548-
writeToFile(previousPacket.address, previousPacket.size, 0);
576+
writeToFile(previousPacket.address, previousPacket.size, previousPacket.timeframeId, 0);
549577
packetsRecorded++;
550578
previousPacket.clear();
551579
}
@@ -568,11 +596,12 @@ class ConsumerFileRecorder : public Consumer
568596
previousPacket.isCopy = true;
569597
}
570598
previousPacket.isEmptyHBStart = true;
599+
previousPacket.timeframeId = b->getData()->header.timeframeId;
571600
} else {
572601

573602
// write packet
574603
// use offsetNextPacket instead of memorySize for file to be consistent
575-
writeToFile(baseAddress + pageOffset, (size_t)h.getOffsetNextPacket(), 0);
604+
writeToFile(baseAddress + pageOffset, (size_t)h.getOffsetNextPacket(), b->getData()->header.timeframeId, 0);
576605
packetsRecorded++;
577606
}
578607

@@ -610,6 +639,7 @@ class ConsumerFileRecorder : public Consumer
610639
int recordWithDataBlockHeader = 0; // if set, internal readout headers are included in file
611640
unsigned long long maxFileSize = 0; // maximum number of bytes to write (in each file)
612641
int maxFilePages = 0; // maximum number of pages to write (in each file)
642+
int maxFileTF = 0; // maximum number of TF to write (in each file)
613643
int filesMax = 0; // maximum number of files to write (for each stream)
614644
int dropEmptyHBFrames = 0; // if set, some empty packets are discarded (see logic in code)
615645

@@ -620,6 +650,7 @@ class ConsumerFileRecorder : public Consumer
620650
void* address = nullptr;
621651
size_t size = 0;
622652
bool isCopy = false;
653+
uint64_t timeframeId = undefinedTimeframeId;
623654
void clear()
624655
{
625656
isEmptyHBStart = false;
@@ -629,6 +660,7 @@ class ConsumerFileRecorder : public Consumer
629660
address = nullptr;
630661
size = 0;
631662
isCopy = false;
663+
timeframeId = undefinedTimeframeId;
632664
}
633665
Packet() {}
634666
~Packet() { clear(); }

src/ConsumerStats.cxx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@ class ConsumerStats : public Consumer
189189
if (bufferReport.length()) {
190190
theLog.log(LogInfoOps_(3003), "Memory buffers usage: %s", bufferReport.c_str());
191191
}
192+
//theLog.log(LogInfoOps_(3003), "orbit=0x%X", (unsigned int) gReadoutStats.counters.currentOrbit.load());
192193
}
193194
}
194195

src/ConsumerZmq.cxx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,6 @@ class ConsumerZMQ : public Consumer
105105
}
106106
zh = zmq_socket(context, ZMQ_PUB);
107107
if (zh==nullptr) { linerr=__LINE__; zmqerr=zmq_errno(); break; }
108-
zmqerr = zmq_bind(zh, cfgAddress.c_str());
109108
if (zmqerr) { linerr=__LINE__; break; }
110109
zmqerr = zmq_setsockopt(zh, ZMQ_CONFLATE, &cfg_ZMQ_CONFLATE, sizeof(cfg_ZMQ_CONFLATE));
111110
if (zmqerr) { linerr=__LINE__; break; }
@@ -117,6 +116,8 @@ class ConsumerZMQ : public Consumer
117116
if (zmqerr) { linerr=__LINE__; break; }
118117
zmqerr = zmq_setsockopt(zh, ZMQ_SNDTIMEO, (void*)&cfg_ZMQ_SNDTIMEO, sizeof(cfg_ZMQ_SNDTIMEO));
119118
if (zmqerr) { linerr=__LINE__; break; }
119+
// options (eg CONFLATE) should be set before binding server
120+
zmqerr = zmq_bind(zh, cfgAddress.c_str());
120121
break;
121122
}
122123

src/CounterStats.cxx

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,3 +153,35 @@ void CounterStats::getHisto(std::vector<double>& x, std::vector<CounterValue>& c
153153
}
154154
}
155155

156+
double CounterStats::getStdDev()
157+
{
158+
double sum = 0;
159+
CounterValue count = 0;
160+
double avg = getAverage();
161+
if (histoNbin) {
162+
for (unsigned int i = 0; i < histoNbin; i++) {
163+
double x;
164+
if (histoLogScale) {
165+
x = histoVmax * pow(histoStep, histoNbin - 1 - i);
166+
} else {
167+
if (i == 0) {
168+
x = histoVmin;
169+
} else if (i == histoNbin - 1) {
170+
x = histoVmax;
171+
} else {
172+
x = histoVmin + (i - 1) * histoStep;
173+
}
174+
}
175+
CounterValue c = histoCounts[i];
176+
if (c) {
177+
double d = (x-avg);
178+
sum += c * d * d;
179+
count += c;
180+
}
181+
}
182+
}
183+
if (count) {
184+
return sqrt(sum/(count-1));
185+
}
186+
return 0;
187+
}

src/CounterStats.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ class CounterStats
3232
CounterValue get(); // get latest value
3333
CounterValue getTotal(); // get total of previous values set
3434
double getAverage();
35+
double getStdDev(); // get standard deviation (when histogram enabled)
3536
CounterValue getMinimum();
3637
CounterValue getMaximum();
3738
CounterValue getCount();

0 commit comments

Comments
 (0)