Skip to content

Commit 6e129f1

Browse files
committed
recording file limit in timeframes
1 parent e93913f commit 6e129f1

File tree

2 files changed

+42
-9
lines changed

2 files changed

+42
-9
lines changed

doc/releaseNotes.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -466,3 +466,4 @@ This file describes the main feature changes for each readout.exe released versi
466466
- Updated configuration parameters:
467467
- equipment-*.verbose: adds some extra verbosity.
468468
- 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.

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(); }

0 commit comments

Comments
 (0)