@@ -126,10 +126,10 @@ DataRelayer::ActivityStats DataRelayer::processDanglingInputs(std::vector<Expira
126126 // We check that no data is already there for the given cell
127127 // it is enough to check the first element
128128 auto & part = mCache [ti * mDistinctRoutesIndex .size () + expirator.routeIndex .value ];
129- if (part.size () > 0 && part[ 0 ] .header != nullptr ) {
129+ if (part.size () > 0 && part.header ( 0 ) != nullptr ) {
130130 continue ;
131131 }
132- if (part.size () > 0 && part[ 0 ] .payload != nullptr ) {
132+ if (part.size () > 0 && part.payload ( 0 ) != nullptr ) {
133133 continue ;
134134 }
135135 // We check that the cell can actually be expired.
@@ -145,16 +145,14 @@ DataRelayer::ActivityStats DataRelayer::processDanglingInputs(std::vector<Expira
145145
146146 assert (ti * mDistinctRoutesIndex .size () + expirator.routeIndex .value < mCache .size ());
147147 assert (expirator.handler );
148- // expired, so we create one entry
149- if (part.size () == 0 ) {
150- part.parts .resize (1 );
151- }
152- expirator.handler (services, part[0 ], variables);
148+ PartRef newRef;
149+ expirator.handler (services, newRef, variables);
150+ part.reset (std::move (newRef));
153151 activity.expiredSlots ++;
154152
155153 mTimesliceIndex .markAsDirty (slot, true );
156- assert (part[ 0 ] .header != nullptr );
157- assert (part[ 0 ] .payload != nullptr );
154+ assert (part.header ( 0 ) != nullptr );
155+ assert (part.payload ( 0 ) != nullptr );
158156 }
159157 }
160158 return activity;
@@ -163,7 +161,7 @@ DataRelayer::ActivityStats DataRelayer::processDanglingInputs(std::vector<Expira
163161// / This does the mapping between a route and a InputSpec. The
164162// / reason why these might diffent is that when you have timepipelining
165163// / you have one route per timeslice, even if the type is the same.
166- size_t matchToContext (void * data,
164+ size_t matchToContext (void const * data,
167165 std::vector<DataDescriptorMatcher> const & matchers,
168166 std::vector<size_t > const & index,
169167 VariableContext& context)
@@ -203,19 +201,13 @@ void sendVariableContextMetrics(VariableContext& context, TimesliceSlot slot,
203201}
204202
205203DataRelayer::RelayChoice
206- DataRelayer::relay (std::unique_ptr<FairMQMessage>& header,
207- std::unique_ptr<FairMQMessage>& payload)
208- {
209- return relay (header, &payload, 1 );
210- }
211-
212- DataRelayer::RelayChoice
213- DataRelayer::relay (std::unique_ptr<FairMQMessage>& firstPart,
214- std::unique_ptr<FairMQMessage>* restOfParts,
215- size_t restOfPartsSize)
204+ DataRelayer::relay (void const * rawHeader,
205+ std::unique_ptr<FairMQMessage>* messages,
206+ size_t nMessages,
207+ size_t nPayloads)
216208{
217209 std::scoped_lock<LockableBase (std::recursive_mutex)> lock (mMutex );
218- DataProcessingHeader const * dph = o2::header::get<DataProcessingHeader*>(firstPart-> GetData () );
210+ DataProcessingHeader const * dph = o2::header::get<DataProcessingHeader*>(rawHeader );
219211 // STATE HOLDING VARIABLES
220212 // This is the class level state of the relaying. If we start supporting
221213 // multithreading this will have to be made thread safe before we can invoke
@@ -238,12 +230,12 @@ DataRelayer::RelayChoice
238230 // become more complicated when we will start supporting ranges.
239231 auto getInputTimeslice = [&matchers = mInputMatchers ,
240232 &distinctRoutes = mDistinctRoutesIndex ,
241- &firstPart ,
233+ &rawHeader ,
242234 &index](VariableContext& context)
243235 -> std::tuple<int , TimesliceId> {
244236 // / FIXME: for the moment we only use the first context and reset
245237 // / between one invokation and the other.
246- auto input = matchToContext (firstPart-> GetData () , matchers, distinctRoutes, context);
238+ auto input = matchToContext (rawHeader , matchers, distinctRoutes, context);
247239
248240 if (input == INVALID_INPUT ) {
249241 return {
@@ -285,24 +277,24 @@ DataRelayer::RelayChoice
285277 };
286278
287279 // Actually save the header / payload in the slot
288- auto saveInSlot = [&firstPart ,
289- &cachedStateMetrics = mCachedStateMetrics ,
290- &restOfParts ,
291- &restOfPartsSize ,
280+ auto saveInSlot = [&cachedStateMetrics = mCachedStateMetrics ,
281+ &messages ,
282+ &nMessages ,
283+ &nPayloads ,
292284 &cache,
293285 &numInputTypes,
294286 &metrics](TimesliceId timeslice, int input, TimesliceSlot slot) {
295287 auto cacheIdx = numInputTypes * slot.index + input;
296- std::vector<PartRef>& parts = cache[cacheIdx]. parts ;
288+ MessageSet& target = cache[cacheIdx];
297289 cachedStateMetrics[cacheIdx] = CacheEntryStatus::PENDING ;
298290 // TODO: make sure that multiple parts can only be added within the same call of
299291 // DataRelayer::relay
300- PartRef entry{ std::move (firstPart), std::move (restOfParts[ 0 ])} ;
301- parts. emplace_back ( std::move (entry) );
302- auto rest = restOfParts + 1 ;
303- for ( size_t pi = 0 ; pi < (restOfPartsSize - 1 ) / 2 ; ++pi) {
304- PartRef entry{ std::move (rest[pi * 2 ]), std::move (rest[pi * 2 + 1 ])} ;
305- parts. emplace_back ( std::move (entry)) ;
292+ assert (nPayloads == 1 ) ;
293+ assert (nMessages % 2 == 0 );
294+ for ( size_t mi = 0 ; mi < nMessages; ++mi) {
295+ assert (mi + nPayloads < nMessages);
296+ target. add ([&messages, &mi]( size_t i) -> FairMQMessagePtr& { return messages[mi + i]; }, nPayloads + 1 ) ;
297+ mi += nPayloads ;
306298 }
307299 };
308300
@@ -390,9 +382,10 @@ DataRelayer::RelayChoice
390382 VariableContext pristineContext;
391383 std::tie (input, timeslice) = getInputTimeslice (pristineContext);
392384
393- auto DataHeaderInfo = [&firstPart ]() {
385+ auto DataHeaderInfo = [&rawHeader ]() {
394386 std::string error;
395- const auto * dh = o2::header::get<o2::header::DataHeader*>(firstPart->GetData ());
387+ // extract header from message model
388+ const auto * dh = o2::header::get<o2::header::DataHeader*>(rawHeader);
396389 if (dh) {
397390 error += fmt::format (" {}/{}/{}" , dh->dataOrigin , dh->dataDescription , dh->subSpecification );
398391 } else {
@@ -405,10 +398,8 @@ DataRelayer::RelayChoice
405398 LOG (ERROR ) << " Could not match incoming data to any input route: " << DataHeaderInfo ();
406399 mStats .malformedInputs ++;
407400 mStats .droppedIncomingMessages ++;
408- firstPart.reset (nullptr );
409- for (size_t pi = 0 ; pi < restOfPartsSize; ++pi) {
410- auto & payload = restOfParts[pi];
411- payload.reset (nullptr );
401+ for (size_t pi = 0 ; pi < nMessages; ++pi) {
402+ messages[pi].reset (nullptr );
412403 }
413404 return Invalid;
414405 }
@@ -417,10 +408,8 @@ DataRelayer::RelayChoice
417408 LOG (ERROR ) << " Could not determine the timeslice for input: " << DataHeaderInfo ();
418409 mStats .malformedInputs ++;
419410 mStats .droppedIncomingMessages ++;
420- firstPart.reset (nullptr );
421- for (size_t pi = 0 ; pi < restOfPartsSize; ++pi) {
422- auto & payload = restOfParts[pi];
423- payload.reset (nullptr );
411+ for (size_t pi = 0 ; pi < nMessages; ++pi) {
412+ messages[pi].reset (nullptr );
424413 }
425414 return Invalid;
426415 }
@@ -447,10 +436,8 @@ DataRelayer::RelayChoice
447436 LOG (WARNING ) << " Incoming data is invalid, not relaying." ;
448437 mStats .malformedInputs ++;
449438 mStats .droppedIncomingMessages ++;
450- firstPart.reset (nullptr );
451- for (size_t pi = 0 ; pi < restOfPartsSize; ++pi) {
452- auto & payload = restOfParts[pi];
453- payload.reset (nullptr );
439+ for (size_t pi = 0 ; pi < nMessages; ++pi) {
440+ messages[pi].reset (nullptr );
454441 }
455442 return Invalid;
456443 case TimesliceIndex::ActionTaken::ReplaceUnused:
@@ -518,11 +505,12 @@ void DataRelayer::getReadyToProcess(std::vector<DataRelayer::RecordAction>& comp
518505 continue ;
519506 }
520507 auto partial = getPartialRecord (li);
508+ // TODO: get the data ref from message model
521509 auto getter = [&partial](size_t idx, size_t part) {
522- if (partial[idx].size () > 0 && partial[idx].at (part). header && partial[idx].at (part). payload ) {
510+ if (partial[idx].size () > 0 && partial[idx].header (part) && partial[idx].payload (part)) {
523511 return DataRef{nullptr ,
524- reinterpret_cast <const char *>(partial[idx].at (part). header ->GetData ()),
525- reinterpret_cast <const char *>(partial[idx].at (part). payload ->GetData ())};
512+ reinterpret_cast <const char *>(partial[idx].header (part)->GetData ()),
513+ reinterpret_cast <const char *>(partial[idx].payload (part)->GetData ())};
526514 }
527515 return DataRef{};
528516 };
@@ -657,6 +645,9 @@ void DataRelayer::publishMetrics()
657645 std::scoped_lock<LockableBase (std::recursive_mutex)> lock (mMutex );
658646
659647 auto numInputTypes = mDistinctRoutesIndex .size ();
648+ // FIXME: many of the DataRelayer function rely on allocated cache, so its
649+ // maybe misleading to have the allocation in a function primarily for
650+ // metrics publishing, do better in setPipelineLength?
660651 mCache .resize (numInputTypes * mTimesliceIndex .size ());
661652 mMetrics .send ({(int )numInputTypes, " data_relayer/h" , Verbosity::Debug});
662653 mMetrics .send ({(int )mTimesliceIndex .size (), " data_relayer/w" , Verbosity::Debug});
0 commit comments