1 /**************************************************************************
2 * This file is property of and copyright by the ALICE HLT Project *
3 * ALICE Experiment at CERN, All rights reserved. *
5 * Primary Authors: Artur Szostak <artursz@iafrica.com> *
6 * for The ALICE HLT Project. *
8 * Permission to use, copy, modify and distribute this software and its *
9 * documentation strictly for non-commercial purposes is hereby granted *
10 * without fee, provided that the above copyright notice appears in all *
11 * copies and that both the copyright notice and this permission notice *
12 * appear in the supporting documentation. The authors make no claims *
13 * about the suitability of this software for any purpose. It is *
14 * provided "as is" without express or implied warranty. *
15 **************************************************************************/
17 /// @file AliHLTTriggerDomain.cxx
18 /// @author Artur Szostak <artursz@iafrica.com>
20 /// @brief Implementation of the AliHLTTriggerDomain class.
22 /// The trigger domain class is the set of HLT raw data block types that should
23 /// be readout and sent to HLTOUT.
27 #include "AliHLTTriggerDomain.h"
28 #include "AliHLTDomainEntry.h"
29 #include "AliHLTReadoutList.h"
30 #include "Riostream.h"
31 #include "TObjArray.h"
32 #include "TObjString.h"
33 #include "AliHLTDAQ.h"
35 ClassImp(AliHLTTriggerDomain)
38 AliHLTTriggerDomain::AliHLTTriggerDomain() :
39 TObject(), fEntries(AliHLTDomainEntry::Class(), 10)
41 // Default constructor.
45 AliHLTTriggerDomain::AliHLTTriggerDomain(const char* list) :
46 TObject(), fEntries(AliHLTDomainEntry::Class(), 10)
48 // Constructs the domain from a list of entries.
51 TObjArray* entries = lst.Tokenize(",");
52 for (Int_t i = 0; i < entries->GetEntriesFast(); i++)
54 TString entry = static_cast<TObjString*>(entries->UncheckedAt(i))->GetString();
55 TObjArray* domainStrings = entry.Tokenize(":");
56 if (domainStrings->GetEntriesFast() <= 0 or domainStrings->GetEntriesFast() > 3)
58 Error("AliHLTTriggerDomain",
59 "The domain string must contain 1, 2 or 3 fields separated by a ':'."
65 bool inclusiveEntry = true;
66 TString typeString = "*******";
67 if (domainStrings->GetEntriesFast() >= 1)
69 typeString = static_cast<TObjString*>(domainStrings->UncheckedAt(0))->GetString();
70 if (typeString.Length() > 0)
72 if (typeString[0] == '+')
74 inclusiveEntry = true;
75 typeString.Remove(0, 1);
77 if (typeString[0] == '-')
79 inclusiveEntry = false;
80 typeString.Remove(0, 1);
84 TString originString = "***";
85 if (domainStrings->GetEntriesFast() >= 2)
87 originString = static_cast<TObjString*>(domainStrings->UncheckedAt(1))->GetString();
91 if (domainStrings->GetEntriesFast() == 3)
93 TString specString = static_cast<TObjString*>(domainStrings->UncheckedAt(2))->GetString();
95 spec = UInt_t( strtoul(specString.Data(), &error, 0) );
96 if (error == NULL or *error != '\0')
98 Error("AliHLTTriggerDomain",
99 "The last field of the domain string must be a number, but we received '%s'.",
112 Add(typeString.Data(), originString.Data(), spec);
114 Remove(typeString.Data(), originString.Data(), spec);
119 Add(typeString.Data(), originString.Data());
121 Remove(typeString.Data(), originString.Data());
124 delete domainStrings;
130 AliHLTTriggerDomain::AliHLTTriggerDomain(const AliHLTReadoutList& list) :
131 TObject(), fEntries(AliHLTDomainEntry::Class(), 10)
133 // Constructor creates a trigger domain from a readout list.
134 // See header file for more details.
140 AliHLTTriggerDomain::AliHLTTriggerDomain(const AliHLTTriggerDomain& domain) :
142 fEntries(AliHLTDomainEntry::Class(), domain.fEntries.GetEntriesFast())
144 // Copy constructor performs a deep copy.
145 // See header file for more details.
147 for (Int_t i = 0; i < domain.fEntries.GetEntriesFast(); i++)
149 const AliHLTDomainEntry* entry = static_cast<const AliHLTDomainEntry*>( domain.fEntries[i] );
150 new (fEntries[fEntries.GetEntriesFast()]) AliHLTDomainEntry(*entry);
155 AliHLTTriggerDomain::~AliHLTTriggerDomain()
157 // Default destructor.
161 void AliHLTTriggerDomain::Add(const AliHLTReadoutList& list)
163 // Adds the readout list to the trigger domain.
164 // See header file for more details.
167 AliHLTReadoutList::kITSSPD, AliHLTReadoutList::kITSSDD, AliHLTReadoutList::kITSSSD,
168 AliHLTReadoutList::kTPC, AliHLTReadoutList::kTRD, AliHLTReadoutList::kTOF,
169 AliHLTReadoutList::kHMPID, AliHLTReadoutList::kPHOS, AliHLTReadoutList::kCPV,
170 AliHLTReadoutList::kPMD, AliHLTReadoutList::kMUONTRK, AliHLTReadoutList::kMUONTRG,
171 AliHLTReadoutList::kFMD, AliHLTReadoutList::kT0, AliHLTReadoutList::kV0,
172 AliHLTReadoutList::kZDC, AliHLTReadoutList::kACORDE, AliHLTReadoutList::kTRG,
173 AliHLTReadoutList::kEMCAL, AliHLTReadoutList::kDAQTEST, AliHLTReadoutList::kHLT
176 for (Int_t deti = 0; deti < AliHLTDAQ::NumberOfDetectors() && deti<(sizeof(detId)/sizeof(Int_t)); deti++)
178 if (list.DetectorEnabled(detId[deti]))
180 Add("DAQRDOUT", AliHLTDAQ::OnlineName(deti));
184 for (Int_t i = 0; i < AliHLTDAQ::NumberOfDdls(deti); i++)
186 Int_t ddlId = AliHLTDAQ::DdlID(deti, i);
187 if (list.IsDDLEnabled(ddlId)) Add("DAQRDOUT", AliHLTDAQ::OnlineName(deti), ddlId);
193 void AliHLTTriggerDomain::Add(const AliHLTDomainEntry& entry)
195 // Adds a new domain entry to the trigger domain.
196 // See header file for more details.
198 AliHLTDomainEntry intersect;
199 bool alreadyInSet = false;
201 // Get the initial size of the fEntries array since we might add things to the
202 // end during the calculation.
203 Int_t count = fEntries.GetEntriesFast();
205 // Go through each entry that is already in fEntries and see if we can remove
206 // it because it will become redundant, or if we need to patch exclusion entries
207 // by adding inclusive intersects, or if we do not even need to add the new entry
208 // because it is already part of the trigger domain.
209 for (Int_t i = 0; i < count; i++)
211 AliHLTDomainEntry* ientry = static_cast<AliHLTDomainEntry*>(fEntries[i]);
212 if (ientry->Inclusive())
214 if (entry.SubsetOf(*ientry))
218 else if (ientry->SubsetOf(entry))
220 ientry->SetBit(14, true); // mark for removal.
225 if (ientry->SubsetOf(entry))
227 ientry->SetBit(14, true); // mark for removal.
229 else if (entry.SubsetOf(*ientry))
231 alreadyInSet = false;
233 else if (ientry->IntersectWith(entry, intersect))
235 MarkForDeletionSubsetsOf(intersect, count);
236 new (fEntries[fEntries.GetEntriesFast()]) AliHLTDomainEntry(kFALSE, intersect);
241 // Check if we need to add the new entry.
242 if (not alreadyInSet)
244 MarkForDeletionSubsetsOf(entry, count);
245 new (fEntries[fEntries.GetEntriesFast()]) AliHLTDomainEntry(kFALSE, entry);
247 RemoveMarkedEntries();
251 void AliHLTTriggerDomain::Add(const AliHLTComponentDataType& datatype)
253 // Adds a new domain entry with the given data type to the trigger domain.
254 // But the data block specification is set to the any matching wild card.
255 // See header file for more details.
257 Add(AliHLTDomainEntry(datatype));
261 void AliHLTTriggerDomain::Add(const char* blocktype, const char* origin)
263 // Adds a new domain entry with the given data type and origin to the trigger domain.
264 // But the data block specification is set to the any matching wild card.
265 // See header file for more details.
267 Add(AliHLTDomainEntry(blocktype, origin));
271 void AliHLTTriggerDomain::Add(const AliHLTComponentDataType& datatype, UInt_t spec)
273 // Adds a new domain entry to the trigger domain with the data type and data block
274 // specification bits.
275 // See header file for more details.
277 Add(AliHLTDomainEntry(datatype, spec));
281 void AliHLTTriggerDomain::Add(const char* blocktype, const char* origin, UInt_t spec)
283 // Adds a new domain entry to the trigger domain with the given data type, origin
284 // and data block specification bits.
285 // See header file for more details.
287 Add(AliHLTDomainEntry(blocktype, origin, spec));
291 void AliHLTTriggerDomain::Remove(const AliHLTReadoutList& list)
293 // Removes the entries in the readout list from the trigger domain that are enabled.
294 // See header file for more details.
297 AliHLTReadoutList::kITSSPD, AliHLTReadoutList::kITSSDD, AliHLTReadoutList::kITSSSD,
298 AliHLTReadoutList::kTPC, AliHLTReadoutList::kTRD, AliHLTReadoutList::kTOF,
299 AliHLTReadoutList::kHMPID, AliHLTReadoutList::kPHOS, AliHLTReadoutList::kCPV,
300 AliHLTReadoutList::kPMD, AliHLTReadoutList::kMUONTRK, AliHLTReadoutList::kMUONTRG,
301 AliHLTReadoutList::kFMD, AliHLTReadoutList::kT0, AliHLTReadoutList::kV0,
302 AliHLTReadoutList::kZDC, AliHLTReadoutList::kACORDE, AliHLTReadoutList::kTRG,
303 AliHLTReadoutList::kEMCAL, AliHLTReadoutList::kDAQTEST, AliHLTReadoutList::kHLT
306 for (Int_t deti = 0; deti < AliHLTDAQ::NumberOfDetectors() && deti<(sizeof(detId)/sizeof(Int_t)); deti++)
308 if (list.DetectorEnabled(detId[deti]))
310 Remove("DAQRDOUT", AliHLTDAQ::OnlineName(deti));
314 for (Int_t i = 0; i < AliHLTDAQ::NumberOfDdls(deti); i++)
316 Int_t ddlId = AliHLTDAQ::DdlID(deti, i);
317 if (list.IsDDLEnabled(ddlId)) Remove("DAQRDOUT", AliHLTDAQ::OnlineName(deti), ddlId);
324 void AliHLTTriggerDomain::Remove(const AliHLTDomainEntry& entry)
326 // Removes the given domain entry from the trigger domain.
327 // See header file for more details.
329 AliHLTDomainEntry intersect;
330 bool addToExcludeSet = false;
332 // Get the initial size of the fEntries array since we might add things to the
333 // end during the calculation.
334 Int_t count = fEntries.GetEntriesFast();
336 // We need to go through all existing entries and see if they need to be removed
337 // because they would become redundant when we add the new 'entry' to the end of
338 // the fEntries list. We also need to check if the new entry needs to be added
339 // at all because the trigger domain might already not contain those entries.
340 // Lastly, some intersection entries might need to be added to patch up existing
341 // inclusive trigger domain entries (rules / patterns).
342 for (Int_t i = 0; i < count; i++)
344 AliHLTDomainEntry* ientry = static_cast<AliHLTDomainEntry*>(fEntries[i]);
345 if (ientry->Inclusive())
347 if (ientry->SubsetOf(entry))
349 ientry->SetBit(14, true); // mark for removal.
351 else if (entry.SubsetOf(*ientry))
353 addToExcludeSet = true;
355 else if (ientry->IntersectWith(entry, intersect))
357 new (fEntries[fEntries.GetEntriesFast()]) AliHLTDomainEntry(kTRUE, intersect);
362 if (entry.SubsetOf(*ientry))
364 addToExcludeSet = false;
366 else if (ientry->SubsetOf(entry))
368 ientry->SetBit(14, true); // mark for removal.
373 // Check if we need to add the new entry.
376 MarkForDeletionSubsetsOf(entry, count);
377 new (fEntries[fEntries.GetEntriesFast()]) AliHLTDomainEntry(kTRUE, entry);
379 RemoveMarkedEntries();
383 void AliHLTTriggerDomain::Remove(const AliHLTComponentDataType& datatype)
385 // Removes the domain entries that have the given data type from the trigger domain.
386 // See header file for more details.
388 Remove(AliHLTDomainEntry(datatype));
392 void AliHLTTriggerDomain::Remove(const char* blocktype, const char* origin)
394 // Removes the domain entries that have the given data type and origin from the
396 // See header file for more details.
398 Remove(AliHLTDomainEntry(blocktype, origin));
402 void AliHLTTriggerDomain::Remove(const AliHLTComponentDataType& datatype, UInt_t spec)
404 // Removes the domain entries that have the given data type and data block
405 // specification bits from the trigger domain.
406 // See header file for more details.
408 Remove(AliHLTDomainEntry(datatype, spec));
412 void AliHLTTriggerDomain::Remove(const char* blocktype, const char* origin, UInt_t spec)
414 // Removes the domain entries that have the given data type, origin and data
415 // block specification bits from the trigger domain.
416 // See header file for more details.
418 Remove(AliHLTDomainEntry(blocktype, origin, spec));
422 bool AliHLTTriggerDomain::Contains(const AliHLTDomainEntry& entry) const
424 // Checks to see if the given domain entry is part of the trigger domain set.
425 // See header file for more details.
427 // Simply go through the whole list of fEntries and for each entry see if the
428 // given domain entry 'entry' being checked matches. If there is a match then
429 // update the result depending on the entry type. i.e. set to false if the entry
430 // in fEntries is an exclusion and set to true if it is an inclusion.
432 for (Int_t i = 0; i < fEntries.GetEntriesFast(); i++)
434 const AliHLTDomainEntry* ientry = static_cast<const AliHLTDomainEntry*>(fEntries[i]);
435 if (ientry->Inclusive())
437 if (*ientry == entry) result = true;
441 if (entry.SubsetOf(*ientry)) result = false;
448 bool AliHLTTriggerDomain::IncludeInReadout(const AliHLTComponentBlockData* block) const
450 // Checks to see if the given data block is part of the trigger domain set and
451 // should be readout.
452 // See header file for more details.
454 // Same algorithm as for Contains() but applied directly to the data block
455 // descriptor structure.
456 AliHLTDomainEntry blockEntry(block->fDataType, block->fSpecification);
458 for (Int_t i = 0; i < fEntries.GetEntriesFast(); i++)
460 const AliHLTDomainEntry* entry = static_cast<const AliHLTDomainEntry*>(fEntries[i]);
461 if (entry->Inclusive())
463 if (*entry == block) result = true;
467 if (blockEntry.SubsetOf(*entry)) result = false;
474 void AliHLTTriggerDomain::Clear(Option_t* option)
476 // Clears the trigger domain (Removes all entries).
478 fEntries.Clear(option);
482 void AliHLTTriggerDomain::Print(Option_t* /*option*/) const
484 // Prints the trigger domain entries in the order that they are applied.
485 // See header file for more details.
487 cout << "Trigger domain rules (applied in order of first to last):" << endl;
488 for (Int_t i = 0; i < fEntries.GetEntriesFast(); i++)
490 const AliHLTDomainEntry* entry = static_cast<const AliHLTDomainEntry*>( fEntries[i] );
491 if (entry->Inclusive())
501 if (fEntries.GetEntriesFast() == 0)
503 cout << "(empty)" << endl;
508 AliHLTTriggerDomain& AliHLTTriggerDomain::operator = (const AliHLTTriggerDomain& domain)
510 // Assignment operator performs a deep copy.
511 // See header file for more details.
513 if (this == &domain) return *this;
514 TObject::operator = (domain);
516 for (Int_t i = 0; i < domain.fEntries.GetEntriesFast(); i++)
518 const AliHLTDomainEntry* entry = static_cast<const AliHLTDomainEntry*>( domain.fEntries[i] );
519 new (fEntries[fEntries.GetEntriesFast()]) AliHLTDomainEntry(*entry);
525 AliHLTTriggerDomain& AliHLTTriggerDomain::operator |= (const AliHLTTriggerDomain& domain)
527 // This operator performs the set union.
528 // See header file for more details.
530 // Note that we partition the fEntries array into 3 regions for this calculation.
531 // - 0..entriesCount-1 : contains the initial entries of this trigger domain.
532 // - entriesCount..startOfIntersects-1 : is space reserved for the new entries
534 // - startOfIntersects..fEntries.GetEntriesFast()-1 : This will grow as we add
535 // all the new domain intersections created during the calculation.
537 // Get the number of entries now before we start adding more entries from 'domain'.
538 Int_t count = fEntries.GetEntriesFast();
539 // Mark the start location for new intersection entries.
540 Int_t startOfIntersects = count + domain.fEntries.GetEntriesFast();
541 Int_t newIndex = startOfIntersects;
543 // Allocate and initialise a single block of memory so that we do not call new twice.
544 bool* buffer = new bool[startOfIntersects];
545 for (Int_t i = 0; i < startOfIntersects; i++) buffer[i] = false;
546 bool* removeThisEntry = buffer;
547 bool* removeDomainEntry = buffer + count;
549 AliHLTDomainEntry intersect;
551 // The idea behind this algorithm is that we need to add all inclusion domain
552 // entries from 'domain' to this object that will not be redundant, but for
553 // the exclusion entries we patch the fEntries rule set by adding the appropriate
554 // intersections to the end of fEntries.
555 for (Int_t i = 0; i < domain.fEntries.GetEntriesFast(); i++)
557 const AliHLTDomainEntry* newEntry = static_cast<const AliHLTDomainEntry*>( domain.fEntries[i] );
558 for (Int_t j = 0; j < count; j++)
560 const AliHLTDomainEntry* currentEntry = static_cast<const AliHLTDomainEntry*>( fEntries[j] );
561 if (currentEntry->Inclusive() and newEntry->Inclusive())
563 // If either entry is a subset of the other then we do not need to add
564 // both, so make sure to remove the one that is redundant.
565 if (newEntry->SubsetOf(*currentEntry))
567 removeDomainEntry[i] = true;
569 else if (currentEntry->SubsetOf(*newEntry))
571 removeThisEntry[j] = true;
576 if (newEntry->IntersectWith(*currentEntry, intersect))
578 // We can remove all intersections that were already added that will
579 // become redundant when this intersection is added to fEntries.
580 MarkForDeletionSubsetsOf(intersect, startOfIntersects);
582 // Make the new intersection entry an exclusion if the newEntry and
583 // currentEntry flags are the same.
584 bool exclude = newEntry->Exclusive() == currentEntry->Exclusive();
585 new (fEntries[newIndex++]) AliHLTDomainEntry(exclude, intersect);
587 // We can also remove entries that are subsets of another entry in the
588 // opposite list, since they will be redundant when everything is merged
589 // together. For example, remove entry x from fEntries if it is a subset
590 // of entry y in domain.fEntries.
591 if (currentEntry->IdenticalTo(intersect)) removeThisEntry[j] = true;
592 if (newEntry->IdenticalTo(intersect)) removeDomainEntry[i] = true;
598 MergeEntries(removeThisEntry, count, removeDomainEntry, startOfIntersects, domain);
605 AliHLTTriggerDomain& AliHLTTriggerDomain::operator ^= (const AliHLTTriggerDomain& domain)
607 // This operator performs the set union, less the set intersect (something like and xor).
608 // See header file for more details.
610 // Note that we partition the fEntries array into 3 regions for this calculation.
611 // - 0..entriesCount-1 : contains the initial entries of this trigger domain.
612 // - entriesCount..startOfIntersects-1 : is space reserved for the new entries
614 // - startOfIntersects..fEntries.GetEntriesFast()-1 : This will grow as we add
615 // all the new domain intersections created during the calculation.
617 // Get the number of entries now before we start adding more entries from 'domain'.
618 Int_t count = fEntries.GetEntriesFast();
619 // Mark the start location for new intersection entries.
620 Int_t startOfIntersects = count + domain.fEntries.GetEntriesFast();
621 Int_t newIndex = startOfIntersects;
623 // Allocate and initialise a single block of memory so that we do not call new twice.
624 bool* buffer = new bool[startOfIntersects];
625 for (Int_t i = 0; i < startOfIntersects; i++) buffer[i] = false;
626 bool* removeThisEntry = buffer;
627 bool* removeDomainEntry = buffer + count;
629 AliHLTDomainEntry intersect;
631 // This algorithm is similar to the case for the set union (operator |=), except
632 // that we make sure to remove from the trigger domain all parts where the entries
633 // from fEntries and domain.fEntries intersect.
634 // This is done by adding the intersections to the end of fEntries such that they
635 // effectively remove those overlapping trigger domain entries when calculating
636 // IncludeInReadout() or Contains().
637 for (Int_t i = 0; i < domain.fEntries.GetEntriesFast(); i++)
639 const AliHLTDomainEntry* newEntry = static_cast<const AliHLTDomainEntry*>( domain.fEntries[i] );
640 for (Int_t j = 0; j < count; j++)
642 const AliHLTDomainEntry* currentEntry = static_cast<const AliHLTDomainEntry*>( fEntries[j] );
643 if (newEntry->IntersectWith(*currentEntry, intersect))
645 // We can remove all intersections that were already added that will
646 // become redundant when this intersection is added to fEntries.
647 MarkForDeletionSubsetsOf(intersect, startOfIntersects);
649 // Make the new intersection entry an exclusion if the newEntry and
650 // currentEntry flags are the same.
651 bool exclude = newEntry->Exclusive() == currentEntry->Exclusive();
652 new (fEntries[newIndex++]) AliHLTDomainEntry(exclude, intersect);
654 // We can also remove entries that are subsets of another entry in the
655 // opposite list, since they will be redundant when everything is merged
656 // together. For example, remove entry x from fEntries if it is a subset
657 // of entry y in domain.fEntries.
658 if (currentEntry->IdenticalTo(intersect)) removeThisEntry[j] = true;
659 if (newEntry->IdenticalTo(intersect)) removeDomainEntry[i] = true;
664 MergeEntries(removeThisEntry, count, removeDomainEntry, startOfIntersects, domain);
671 AliHLTTriggerDomain& AliHLTTriggerDomain::operator -= (const AliHLTTriggerDomain& domain)
673 // This operator performs the set difference.
674 // See header file for more details.
676 // Mark the number of entries in fEntries now before we start adding more
677 // entries from 'domain' or intersections.
678 Int_t startOfIntersects = fEntries.GetEntriesFast();
679 Int_t newIndex = startOfIntersects;
681 AliHLTDomainEntry intersect;
683 // To compute the set difference we need to remove all all parts that overlap
684 // with 'domain'. i.e. we need to find all the intersects between the domain
685 // entries in fEntries and those in domain.fEntries, and add the intersects
686 // to the fEntries list, such that they will cancel or remove the overlapping
687 // parts of the two trigger domains.
688 for (Int_t i = 0; i < domain.fEntries.GetEntriesFast(); i++)
690 const AliHLTDomainEntry* checkEntry = static_cast<const AliHLTDomainEntry*>( domain.fEntries[i] );
691 if (checkEntry->Inclusive())
693 // For inclusive entries we need to find the overlaps with the inclusive
694 // entries in fEntries and add exclusive entries that will remove that
695 // part of the trigger domain set.
696 for (Int_t j = 0; j < startOfIntersects; j++)
698 AliHLTDomainEntry* currentEntry = static_cast<AliHLTDomainEntry*>( fEntries[j] );
700 // We only need to consider the case where both entries are inclusive,
701 // since an exclusion in fEntries already eliminates those data blocks
702 // from the trigger domain set.
703 if (currentEntry->Exclusive()) continue;
705 if (checkEntry->IntersectWith(*currentEntry, intersect))
707 // We can remove all intersections that were already added that will
708 // become redundant when this intersection is added to fEntries.
709 MarkForDeletionSubsetsOf(intersect, startOfIntersects);
711 new (fEntries[newIndex++]) AliHLTDomainEntry(kTRUE, intersect);
712 if (currentEntry->IdenticalTo(intersect))
714 currentEntry->SetBit(14, true);
721 // For an exclusive entry in 'domain' we need to find the intersections with
722 // all of fEntries and re-apply these with the same exclude flags.
723 for (Int_t j = 0; j < startOfIntersects; j++)
725 AliHLTDomainEntry* currentEntry = static_cast<AliHLTDomainEntry*>( fEntries[j] );
726 if (checkEntry->IntersectWith(*currentEntry, intersect))
728 // We can remove all intersections that were already added that will
729 // become redundant when this intersection is added to fEntries.
730 MarkForDeletionSubsetsOf(intersect, startOfIntersects);
732 new (fEntries[newIndex++]) AliHLTDomainEntry(currentEntry->Exclusive(), intersect);
738 RemoveMarkedEntries();
744 AliHLTTriggerDomain AliHLTTriggerDomain::operator ~ () const
746 // Performs a set complement of the trigger domain.
748 // The set complement is calculated by creating a new trigger domain which
749 // accepts all possible data blocks, and then apply all the trigger domain
750 // entries (rules / patterns) from top to bottom, but apply them with the
751 // opposite meaning. For example, this->fEntries contains an inclusive domain
752 // entry then remove it from the new trigger domain 'result', but if it is
753 // an exclusion then add it.
754 AliHLTTriggerDomain result;
755 result.Add(kAliHLTAnyDataType);
756 for (Int_t i = 0; i < fEntries.GetEntriesFast(); i++)
758 const AliHLTDomainEntry* entry = static_cast<const AliHLTDomainEntry*>( fEntries[i] );
759 if (entry->Inclusive())
761 result.Remove(*entry);
772 AliHLTTriggerDomain AliHLTTriggerDomain::operator & (const AliHLTTriggerDomain& domain) const
774 // This operator finds the set intersect.
775 // See header file for more details.
777 AliHLTTriggerDomain result;
779 AliHLTDomainEntry intersect;
781 // To find the set intersect we need to compare each entry in 'domain' to those
782 // of fEntries. For each inclusive entry in 'domain' we need to add to the result
783 // the intersect between it and each entry of fEntries, with the same exclude flag
784 // value as the domain entry from fEntries.
785 // However, in principle, for the exclusion entries in 'domain' we just add them
786 // to the result, since those entries do not form part of the 'domain' trigger
787 // domain set, so they should not form part of the result (remember any data block
788 // must be contained in both trigger domains for a set intersect).
789 // In actual fact we just add the intersect of the exclusion entries in 'domain'
790 // with those of fEntries to the result. This has the same overall effect, but
791 // makes sure that all exclusion entries are always subsets of inclusion entries.
792 for (Int_t i = 0; i < domain.fEntries.GetEntriesFast(); i++)
794 const AliHLTDomainEntry* checkEntry = static_cast<const AliHLTDomainEntry*>( domain.fEntries[i] );
795 if (checkEntry->Inclusive())
797 for (Int_t j = 0; j < fEntries.GetEntriesFast(); j++)
799 AliHLTDomainEntry* currentEntry = static_cast<AliHLTDomainEntry*>( fEntries[j] );
800 if (checkEntry->IntersectWith(*currentEntry, intersect))
802 // We can remove all entries that were already added to the result that
803 // will become redundent because they are subsets of the new entry.
804 result.MarkForDeletionSubsetsOf(intersect, 0);
806 new (result.fEntries[newIndex++]) AliHLTDomainEntry(currentEntry->Exclusive(), intersect);
812 for (Int_t j = 0; j < fEntries.GetEntriesFast(); j++)
814 AliHLTDomainEntry* currentEntry = static_cast<AliHLTDomainEntry*>( fEntries[j] );
815 if (checkEntry->IntersectWith(*currentEntry, intersect))
817 // We can remove all entries that were already added to the result that
818 // will become redundant because they are subsets of the new entry.
819 result.MarkForDeletionSubsetsOf(intersect, 0);
821 new (result.fEntries[newIndex++]) AliHLTDomainEntry(kTRUE, intersect);
827 result.RemoveMarkedEntries();
833 AliHLTTriggerDomain::operator AliHLTReadoutList () const
835 // Typecast operator which constructs a readout list from the trigger domain.
837 AliHLTReadoutList result;
838 for (Int_t deti = 0; deti < AliHLTDAQ::NumberOfDetectors(); deti++)
840 for (Int_t i = 0; i < AliHLTDAQ::NumberOfDdls(deti); i++)
842 Int_t ddlId = AliHLTDAQ::DdlID(deti, i);
843 if (Contains(AliHLTDomainEntry("DAQRDOUT", AliHLTDAQ::OnlineName(deti), ddlId)))
845 result.EnableDDLBit(ddlId);
853 void AliHLTTriggerDomain::MergeEntries(
854 const bool* removeThisEntry, Int_t entriesCount,
855 const bool* removeDomainEntry, Int_t startOfIntersects,
856 const AliHLTTriggerDomain& domain
859 // Merges the entries in this trigger domain with the ones in 'domain', while
860 // removing all entries that were marked for removal.
861 // See header file for more information.
863 bool anythingRemoved = false;
865 // Remember this method is used at the end of the calculation of the binary operators
866 // and that fEntries is expected to be partitioned into 3 regions.
867 // - 0..entriesCount-1 : contains the original (initial) entries of this trigger domain.
868 // - entriesCount..startOfIntersects-1 : is space reserved for the new entries
869 // from the given trigger domain 'domain' being processed.
870 // - startOfIntersects..fEntries.GetEntriesFast()-1 : contains all new domain entry
871 // intersection created and added to fEntries.
873 // First we need to remove all entries marked for removal from the original entries.
874 for (Int_t i = 0; i < entriesCount; i++)
876 if (removeThisEntry[i])
878 fEntries.RemoveAt(i);
879 anythingRemoved = true;
883 // Now we copy over all the new entries from 'domain' which were not marked for removal
884 // and indicate anythingRemoved = true since there will now be gaps in the clones array
885 // that need to be compressed away later.
886 for (Int_t i = 0; i < domain.fEntries.GetEntriesFast(); i++)
888 if (removeDomainEntry[i])
890 anythingRemoved = true;
894 const AliHLTDomainEntry* newEntry = static_cast<const AliHLTDomainEntry*>( domain.fEntries[i] );
895 new (fEntries[entriesCount+i]) AliHLTDomainEntry(*newEntry);
899 // Finally remove all new intersection entries that were marked for removal by
900 // the MarkForDeletionSubsetsOf method.
901 for (Int_t i = startOfIntersects; i < fEntries.GetEntriesFast(); i++)
903 const AliHLTDomainEntry* ientry = static_cast<const AliHLTDomainEntry*>( fEntries[i] );
904 if (ientry->TestBit(14))
906 fEntries.RemoveAt(i);
907 anythingRemoved = true;
910 if (anythingRemoved) fEntries.Compress();
914 void AliHLTTriggerDomain::MarkForDeletionSubsetsOf(const AliHLTDomainEntry& entry, Int_t min)
916 // Marks for deletion all the entries in this trigger domain that are subsets
917 // of the given entry.
918 // See header file for more information.
920 AliHLTDomainEntry intersect;
921 for (Int_t i = min; i < fEntries.GetEntriesFast(); i++)
923 AliHLTDomainEntry* ientry = static_cast<AliHLTDomainEntry*>( fEntries[i] );
924 if (ientry->TestBit(14)) continue;
925 if (ientry->SubsetOf(entry))
927 ientry->SetBit(14, true);
933 void AliHLTTriggerDomain::RemoveMarkedEntries()
935 // Removes all entries in this trigger domain which were marked for removal.
936 // See header file for more information.
938 bool anythingRemoved = false;
939 for (Int_t i = 0; i < fEntries.GetEntriesFast(); i++)
941 const AliHLTDomainEntry* ientry = static_cast<const AliHLTDomainEntry*>( fEntries[i] );
942 if (ientry->TestBit(14))
944 fEntries.RemoveAt(i);
945 anythingRemoved = true;
948 if (anythingRemoved) fEntries.Compress();
952 void AliHLTTriggerDomain::Optimise()
954 // Removes redundant trigger domain entries from the trigger domain.
955 // See header file for more information.
957 AliHLTDomainEntry intersect;
959 // Check that the first entry is not and exclusion which would be redundent.
960 if (fEntries.GetEntriesFast() == 0) return;
961 AliHLTDomainEntry* firstEntry = static_cast<AliHLTDomainEntry*>( fEntries[0] );
962 if (firstEntry->Exclusive()) firstEntry->SetBit(14, true);
964 for (Int_t i = 1; i < fEntries.GetEntriesFast(); i++)
966 AliHLTDomainEntry* ientry = static_cast<AliHLTDomainEntry*>( fEntries[i] );
968 // For the i'th entry in fEntries, compare it in reverse order with all other
969 // entries that are before it and look for redundant ones, i.e. that are subsets
970 // of the i'th entry.
971 for (Int_t j = i-1; j >= 0; j--)
973 AliHLTDomainEntry* jentry = static_cast<AliHLTDomainEntry*>( fEntries[j] );
974 if (jentry->TestBit(14)) continue;
975 // Find entries that intersect
976 if (jentry->SubsetOf(*ientry))
978 // jentry is a subset of ientry so it is redundant because for all values
979 // ientry will override jentry when calling IncludeInReadout.
980 jentry->SetBit(14, true);
982 else if (*ientry == *jentry)
984 // If intersecting entries have opposite exclude flags then search no further,
985 // we know that we will need this entry for correct behaviour of IncludeInReadout.
986 if (ientry->Inclusive() == jentry->Exclusive()) goto processNextEntry;
988 if (ientry->SubsetOf(*jentry))
990 ientry->SetBit(14, true);
991 goto processNextEntry;
996 // If we got to this point then we hit the top of the trigger domain rules
997 // (pattern matching) list without hitting any and overlapping entries.
998 // So now we need to check if ientry is an exclusion. If it is, then it is
999 // redundant and we can mark it for removal.
1000 if (ientry->Exclusive()) ientry->SetBit(14, true);
1005 RemoveMarkedEntries();