@@ -83,7 +83,7 @@ bool SubTimeFrameReadoutBuilder::addHbFrames(
8383 const auto R = RDHReader (pHbFramesBegin[0 ]);
8484 mStf ->updateFirstOrbit (R.getOrbit ());
8585 } catch (...) {
86- EDDLOG (" Error getting RDHReader instace . Not using {} HBFs" , pHBFrameLen);
86+ EDDLOG (" Error getting RDHReader instance . Not using {} HBFs" , pHBFrameLen);
8787 return false ;
8888 }
8989 }
@@ -230,17 +230,32 @@ std::optional<std::unique_ptr<SubTimeFrame>> SubTimeFrameReadoutBuilder::addTopo
230230 const o2::header::DataOrigin &pDataOrig,
231231 const o2::header::DataHeader::SubSpecificationType pSubSpecification,
232232 const ReadoutSubTimeframeHeader& pHdr,
233- std::vector<FairMQMessagePtr>::iterator pHbFramesBegin, const std::size_t pHBFrameLen,
234- const std::uint64_t pMaxNumMessages)
233+ std::vector<FairMQMessagePtr>::iterator & pHbFramesBegin, std::size_t & pHBFrameLen,
234+ const std::uint64_t pMaxNumMessages, bool pCutTfOnNewOrbit )
235235{
236236 static uint32_t sTfId = 1 ;
237237
238+ auto isFirstPacketOfOrbit = [&](const FairMQMessagePtr &pMsg) -> bool {
239+ if (!pMsg) {
240+ return false ;
241+ }
242+ try {
243+ const auto R = RDHReader (pMsg);
244+ if (R.getPageCounter () == 0 ) {
245+ return true ;
246+ }
247+ } catch (...) {
248+ EDDLOG_RL (5000 , " Error getting RDHReader instance. page_size={}" , pMsg->GetSize ());
249+ }
250+ return false ;
251+ };
252+
238253 if (!mRunning ) {
239254 WDDLOG (" Adding HBFrames while STFBuilder is not running!" );
240255 return std::nullopt ;
241256 }
242257
243- if (!mAcceptStfData ) {
258+ if (!mAcceptStfData || (pHBFrameLen == 0 ) ) {
244259 return std::nullopt ;
245260 }
246261
@@ -259,60 +274,80 @@ std::optional<std::unique_ptr<SubTimeFrame>> SubTimeFrameReadoutBuilder::addTopo
259274 }
260275 }
261276
262- DataHeader lDataHdr (
263- o2::header:: gDataDescriptionRawData ,
264- pDataOrig,
265- pSubSpecification,
266- 0 /* Update later */
267- );
268- lDataHdr. payloadSerializationMethod = gSerializationMethodNone ;
277+ auto lReturnStfIfFinished = [&]( const auto &pHbFrame) -> std::optional<std::unique_ptr<o2::DataDistribution::SubTimeFrame> > {
278+ if (!lStf || (lStfNumMessages == 0 )) {
279+ return std:: nullopt ;
280+ }
281+ // before starting, check if the existing STF is large enough and cut conditions are met
282+ if ((!pCutTfOnNewOrbit && (lStfNumMessages >= pMaxNumMessages)) || // orbit cut not used
283+ (pCutTfOnNewOrbit && (lStfNumMessages >= pMaxNumMessages) && isFirstPacketOfOrbit (pHbFrame))) { // orbit cut used
269284
270- const o2hdr::DataIdentifier lDataId (o2::header:: gDataDescriptionRawData . str , pDataOrig. str );
285+ lStf-> setOrigin (SubTimeFrame::Header::Origin::eReadoutTopology );
271286
272- bool lIncludeO2Hdr = true ;
273- for (size_t i = 0 ; i < pHBFrameLen; i++) {
274- // we need at least one header per equipment
275- if (lIncludeO2Hdr) {
276- lIncludeO2Hdr = false ; // only provide one header message
287+ DDDLOG_RL (1000 , " addTopoStfData: leaving and returning STF: numMessages={}" , lStfNumMessages);
288+ lStfNumMessages = 0 ;
277289
278- lDataHdr.payloadSize = pHbFramesBegin[i]->GetSize ();
290+ mAcceptStfData = true ;
291+ return std::optional<std::unique_ptr<SubTimeFrame>>(std::move (lStf));
292+ }
279293
280- auto lDplHdr = o2::framework::DataProcessingHeader{lStf->header ().mId };
281- lDplHdr.creation = lStf->header ().mCreationTimeMs ;
282- auto lStack = Stack (
283- lDataHdr,
284- lDplHdr
285- );
294+ return std::nullopt ;
295+ };
286296
287- auto lHdrMsg = mMemRes .newHeaderMessage (lStack.data (), lStack.size ());
288- if (!lHdrMsg) {
289- WDDLOG_RL (1000 , " Allocation error: dropping data of the current STF stf_id={}" , pHdr.mRunNumber );
290- // clear data of the partial STF
291- mAcceptStfData = false ;
292- lStf->clear ();
297+ // check if we should cut at the first block
298+ {
299+ auto lDoneStfOpt = lReturnStfIfFinished (*pHbFramesBegin);
300+ if (lDoneStfOpt.has_value ()) {
301+ return lDoneStfOpt;
302+ }
303+ }
293304
294- return std::nullopt ;
295- }
305+ const o2hdr::DataIdentifier lDataId (o2::header::gDataDescriptionRawData .str , pDataOrig.str );
296306
297- lStf->addStfDataReadout (lDataId, pSubSpecification, SubTimeFrame::StfData{std::move (lHdrMsg), std::move (pHbFramesBegin[i])});
298- } else {
299- lStf->addStfDataReadout (lDataId, pSubSpecification, SubTimeFrame::StfData{nullptr , std::move (pHbFramesBegin[i])});
307+ if (!lStf->stfDataExists (lDataId, pSubSpecification)) {
308+ DataHeader lDataHdr (
309+ o2::header::gDataDescriptionRawData ,
310+ pDataOrig,
311+ pSubSpecification,
312+ 0 /* Update later */
313+ );
314+ lDataHdr.payloadSerializationMethod = gSerializationMethodNone ;
315+ lDataHdr.payloadSize = (*pHbFramesBegin)->GetSize ();
316+
317+ auto lDplHdr = o2::framework::DataProcessingHeader{lStf->header ().mId };
318+ lDplHdr.creation = lStf->header ().mCreationTimeMs ;
319+
320+ auto lStack = Stack (lDataHdr, lDplHdr);
321+
322+ auto lHdrMsg = mMemRes .newHeaderMessage (lStack.data (), lStack.size ());
323+ if (!lHdrMsg) {
324+ WDDLOG_RL (10000 , " Allocation error: dropping data of the current STF stf_id={}" , pHdr.mRunNumber );
325+ // clear data of the partial STF
326+ mAcceptStfData = false ;
327+ lStf->clear ();
328+ return std::nullopt ;
300329 }
301- }
302330
303- // update number of messages per topo stf
304- lStfNumMessages += pHBFrameLen;
331+ lStf->addStfDataReadout (lDataId, pSubSpecification, SubTimeFrame::StfData{std::move (lHdrMsg), std::move (*pHbFramesBegin)});
332+ lStfNumMessages += 1 ;
333+ pHBFrameLen -= 1 ;
334+ pHbFramesBegin += 1 ;
335+ }
305336
306- if (lStfNumMessages >= pMaxNumMessages) {
307- lStf->setOrigin (SubTimeFrame::Header::Origin::eReadoutTopology);
308- std::optional<std::unique_ptr<SubTimeFrame>> lRetStf = std::move (lStf);
337+ while (pHBFrameLen > 0 ) {
338+ // check if we should cut at the next
339+ auto lDoneStfOpt = lReturnStfIfFinished (*pHbFramesBegin);
340+ if (lDoneStfOpt.has_value ()) {
341+ return lDoneStfOpt;
342+ }
309343
310- DDDLOG_RL (1000 , " addTopoStfData: leaving and returning STF: numMessages={}" , lStfNumMessages);
311- lStfNumMessages = 0 ;
312- return lRetStf;
344+ lStf->addStfDataReadout (lDataId, pSubSpecification, SubTimeFrame::StfData{nullptr , std::move (*pHbFramesBegin)});
345+ lStfNumMessages += 1 ;
346+ pHBFrameLen -= 1 ;
347+ pHbFramesBegin += 1 ;
313348 }
314349
315- DDDLOG_RL (1000 , " addTopoStfData: leaving without returning STF: numMessages={}" , lStfNumMessages);
350+ DDDLOG_RL (10000 , " addTopoStfData: leaving without returning STF: numMessages={}" , lStfNumMessages);
316351
317352 return std::nullopt ;
318353}
0 commit comments