]> git.uio.no Git - u/mrichter/AliRoot.git/blame - HLT/trigger/AliHLTTriggerDomain.cxx
Finished code for global HLT trigger and the trigger menu implementation.
[u/mrichter/AliRoot.git] / HLT / trigger / AliHLTTriggerDomain.cxx
CommitLineData
1b9a175e 1/**************************************************************************
2 * This file is property of and copyright by the ALICE HLT Project *
3 * ALICE Experiment at CERN, All rights reserved. *
4 * *
5 * Primary Authors: Artur Szostak <artursz@iafrica.com> *
6 * for The ALICE HLT Project. *
7 * *
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 **************************************************************************/
16
17/// @file AliHLTTriggerDomain.cxx
18/// @author Artur Szostak <artursz@iafrica.com>
19/// @date 19 Nov 2008
20/// @brief Implementation of the AliHLTTriggerDomain class.
21///
22/// The trigger domain class is the set of HLT raw data block types that should
23/// be readout and sent to HLTOUT.
24
25#include "AliHLTTriggerDomain.h"
26#include "AliHLTDomainEntry.h"
52f67e50 27#include "AliHLTReadoutList.h"
1b9a175e 28#include "Riostream.h"
52f67e50 29#include "TObjArray.h"
30#include "TObjString.h"
31#include "AliDAQ.h"
1b9a175e 32
33ClassImp(AliHLTTriggerDomain)
34
35
36AliHLTTriggerDomain::AliHLTTriggerDomain() :
37 TObject(), fEntries(AliHLTDomainEntry::Class(), 10)
38{
39 // Default constructor.
40}
41
42
52f67e50 43AliHLTTriggerDomain::AliHLTTriggerDomain(const char* list) :
44 TObject(), fEntries(AliHLTDomainEntry::Class(), 10)
45{
46 // Constructs the domain from a list of entries.
47
48 TString lst = list;
49 TObjArray* entries = lst.Tokenize(",");
50 for (Int_t i = 0; i < entries->GetEntriesFast(); i++)
51 {
52 TString entry = static_cast<TObjString*>(entries->UncheckedAt(i))->GetString();
53 TObjArray* domainStrings = entry.Tokenize(":");
54 if (domainStrings->GetEntriesFast() <= 0 or domainStrings->GetEntriesFast() > 3)
55 {
56 Error("AliHLTTriggerDomain",
57 "The domain string must contain 1, 2 or 3 fields separated by a ':'."
58 );
59 delete domainStrings;
60 continue;
61 }
62
63 bool inclusiveEntry = true;
64 TString typeString = "*******";
65 if (domainStrings->GetEntriesFast() >= 1)
66 {
67 typeString = static_cast<TObjString*>(domainStrings->UncheckedAt(0))->GetString();
68 if (typeString.Length() > 0)
69 {
70 if (typeString[0] == '+')
71 {
72 inclusiveEntry = true;
73 typeString.Remove(0, 1);
74 }
75 if (typeString[0] == '-')
76 {
77 inclusiveEntry = false;
78 typeString.Remove(0, 1);
79 }
80 }
81 }
82 TString originString = "***";
83 if (domainStrings->GetEntriesFast() >= 2)
84 {
85 originString = static_cast<TObjString*>(domainStrings->UncheckedAt(1))->GetString();
86 }
87 bool usespec = false;
88 UInt_t spec = 0;
89 if (domainStrings->GetEntriesFast() == 3)
90 {
91 TString specString = static_cast<TObjString*>(domainStrings->UncheckedAt(2))->GetString();
92 char* error = NULL;
93 spec = UInt_t( strtoul(specString.Data(), &error, 0) );
94 if (error == NULL or *error != '\0')
95 {
96 Error("AliHLTTriggerDomain",
97 "The last field of the domain string must be a number, but we received '%s'.",
98 specString.Data()
99 );
100 }
101 else
102 {
103 usespec = true;
104 }
105 }
106
107 if (usespec)
108 {
109 if (inclusiveEntry)
110 Add(typeString.Data(), originString.Data(), spec);
111 else
112 Remove(typeString.Data(), originString.Data(), spec);
113 }
114 else
115 {
116 if (inclusiveEntry)
117 Add(typeString.Data(), originString.Data());
118 else
119 Remove(typeString.Data(), originString.Data());
120 }
121
122 delete domainStrings;
123 }
124 delete entries;
125}
126
127
128AliHLTTriggerDomain::AliHLTTriggerDomain(const AliHLTReadoutList& list) :
129 TObject(), fEntries(AliHLTDomainEntry::Class(), 10)
130{
131 // Constructor creates a trigger domain from a readout list.
132 // See header file for more details.
133
134 Add(list);
135}
136
137
1b9a175e 138AliHLTTriggerDomain::AliHLTTriggerDomain(const AliHLTTriggerDomain& domain) :
139 TObject(domain),
140 fEntries(AliHLTDomainEntry::Class(), domain.fEntries.GetEntriesFast())
141{
142 // Copy constructor performs a deep copy.
143 // See header file for more details.
144
145 for (Int_t i = 0; i < domain.fEntries.GetEntriesFast(); i++)
146 {
147 const AliHLTDomainEntry* entry = static_cast<const AliHLTDomainEntry*>( domain.fEntries[i] );
148 new (fEntries[fEntries.GetEntriesFast()]) AliHLTDomainEntry(*entry);
149 }
150}
151
152
153AliHLTTriggerDomain::~AliHLTTriggerDomain()
154{
155 // Default destructor.
156}
157
158
52f67e50 159void AliHLTTriggerDomain::Add(const AliHLTReadoutList& list)
160{
161 // Adds the readout list to the trigger domain.
162 // See header file for more details.
163
164 Int_t detId[AliDAQ::kNDetectors] = {
165 AliHLTReadoutList::kITSSPD, AliHLTReadoutList::kITSSDD, AliHLTReadoutList::kITSSSD,
166 AliHLTReadoutList::kTPC, AliHLTReadoutList::kTRD, AliHLTReadoutList::kTOF,
167 AliHLTReadoutList::kHMPID, AliHLTReadoutList::kPHOS, AliHLTReadoutList::kCPV,
168 AliHLTReadoutList::kPMD, AliHLTReadoutList::kMUONTRK, AliHLTReadoutList::kMUONTRG,
169 AliHLTReadoutList::kFMD, AliHLTReadoutList::kT0, AliHLTReadoutList::kV0,
170 AliHLTReadoutList::kZDC, AliHLTReadoutList::kACORDE, AliHLTReadoutList::kTRG,
171 AliHLTReadoutList::kEMCAL, AliHLTReadoutList::kDAQTEST, AliHLTReadoutList::kHLT
172 };
173
174 for (Int_t deti = 0; deti < AliDAQ::kNDetectors; deti++)
175 {
176 if (list.DetectorEnabled(detId[deti]))
177 {
178 Add("DAQRDOUT", AliDAQ::OnlineName(deti));
179 }
180 else
181 {
182 for (Int_t i = 0; i < AliDAQ::NumberOfDdls(deti); i++)
183 {
184 Int_t ddlId = AliDAQ::DdlID(deti, i);
185 if (list.IsDDLEnabled(ddlId)) Add("DAQRDOUT", AliDAQ::OnlineName(deti), ddlId);
186 }
187 }
188 }
189}
190
1b9a175e 191void AliHLTTriggerDomain::Add(const AliHLTDomainEntry& entry)
192{
193 // Adds a new domain entry to the trigger domain.
194 // See header file for more details.
195
196 AliHLTDomainEntry intersect;
1b9a175e 197 bool alreadyInSet = false;
198
199 // Get the initial size of the fEntries array since we might add things to the
200 // end during the calculation.
201 Int_t count = fEntries.GetEntriesFast();
202
203 // Go through each entry that is already in fEntries and see if we can remove
204 // it because it will become redundant, or if we need to patch exclusion entries
205 // by adding inclusive intersects, or if we do not even need to add the new entry
206 // because it is already part of the trigger domain.
207 for (Int_t i = 0; i < count; i++)
208 {
0a76630e 209 AliHLTDomainEntry* ientry = static_cast<AliHLTDomainEntry*>(fEntries[i]);
1b9a175e 210 if (ientry->Inclusive())
211 {
212 if (entry.SubsetOf(*ientry))
213 {
214 alreadyInSet = true;
215 }
216 else if (ientry->SubsetOf(entry))
217 {
0a76630e 218 ientry->SetBit(14, true); // mark for removal.
1b9a175e 219 }
220 }
221 else
222 {
223 if (ientry->SubsetOf(entry))
224 {
0a76630e 225 ientry->SetBit(14, true); // mark for removal.
1b9a175e 226 }
227 else if (entry.SubsetOf(*ientry))
228 {
229 alreadyInSet = false;
230 }
231 else if (ientry->IntersectWith(entry, intersect))
232 {
0a76630e 233 MarkForDeletionSubsetsOf(intersect, count);
1b9a175e 234 new (fEntries[fEntries.GetEntriesFast()]) AliHLTDomainEntry(kFALSE, intersect);
1b9a175e 235 }
236 }
237 }
238
0a76630e 239 // Check if we need to add the new entry.
1b9a175e 240 if (not alreadyInSet)
241 {
0a76630e 242 MarkForDeletionSubsetsOf(entry, count);
1b9a175e 243 new (fEntries[fEntries.GetEntriesFast()]) AliHLTDomainEntry(kFALSE, entry);
244 }
0a76630e 245 RemoveMarkedEntries();
1b9a175e 246}
247
248
249void AliHLTTriggerDomain::Add(const AliHLTComponentDataType& datatype)
250{
251 // Adds a new domain entry with the given data type to the trigger domain.
252 // But the data block specification is set to the any matching wild card.
253 // See header file for more details.
254
255 Add(AliHLTDomainEntry(datatype));
256}
257
258
259void AliHLTTriggerDomain::Add(const char* blocktype, const char* origin)
260{
261 // Adds a new domain entry with the given data type and origin to the trigger domain.
262 // But the data block specification is set to the any matching wild card.
263 // See header file for more details.
264
265 Add(AliHLTDomainEntry(blocktype, origin));
266}
267
268
269void AliHLTTriggerDomain::Add(const AliHLTComponentDataType& datatype, UInt_t spec)
270{
271 // Adds a new domain entry to the trigger domain with the data type and data block
272 // specification bits.
273 // See header file for more details.
274
275 Add(AliHLTDomainEntry(datatype, spec));
276}
277
278
279void AliHLTTriggerDomain::Add(const char* blocktype, const char* origin, UInt_t spec)
280{
281 // Adds a new domain entry to the trigger domain with the given data type, origin
282 // and data block specification bits.
283 // See header file for more details.
284
285 Add(AliHLTDomainEntry(blocktype, origin, spec));
286}
287
288
52f67e50 289void AliHLTTriggerDomain::Remove(const AliHLTReadoutList& list)
290{
291 // Removes the entries in the readout list from the trigger domain that are enabled.
292 // See header file for more details.
293
294 Int_t detId[AliDAQ::kNDetectors] = {
295 AliHLTReadoutList::kITSSPD, AliHLTReadoutList::kITSSDD, AliHLTReadoutList::kITSSSD,
296 AliHLTReadoutList::kTPC, AliHLTReadoutList::kTRD, AliHLTReadoutList::kTOF,
297 AliHLTReadoutList::kHMPID, AliHLTReadoutList::kPHOS, AliHLTReadoutList::kCPV,
298 AliHLTReadoutList::kPMD, AliHLTReadoutList::kMUONTRK, AliHLTReadoutList::kMUONTRG,
299 AliHLTReadoutList::kFMD, AliHLTReadoutList::kT0, AliHLTReadoutList::kV0,
300 AliHLTReadoutList::kZDC, AliHLTReadoutList::kACORDE, AliHLTReadoutList::kTRG,
301 AliHLTReadoutList::kEMCAL, AliHLTReadoutList::kDAQTEST, AliHLTReadoutList::kHLT
302 };
303
304 for (Int_t deti = 0; deti < AliDAQ::kNDetectors; deti++)
305 {
306 if (list.DetectorEnabled(detId[deti]))
307 {
308 Remove("DAQRDOUT", AliDAQ::OnlineName(deti));
309 }
310 else
311 {
312 for (Int_t i = 0; i < AliDAQ::NumberOfDdls(deti); i++)
313 {
314 Int_t ddlId = AliDAQ::DdlID(deti, i);
315 if (list.IsDDLEnabled(ddlId)) Remove("DAQRDOUT", AliDAQ::OnlineName(deti), ddlId);
316 }
317 }
318 }
319}
320
321
1b9a175e 322void AliHLTTriggerDomain::Remove(const AliHLTDomainEntry& entry)
323{
324 // Removes the given domain entry from the trigger domain.
325 // See header file for more details.
326
327 AliHLTDomainEntry intersect;
1b9a175e 328 bool addToExcludeSet = false;
329
330 // Get the initial size of the fEntries array since we might add things to the
331 // end during the calculation.
332 Int_t count = fEntries.GetEntriesFast();
333
334 // We need to go through all existing entries and see if they need to be removed
335 // because they would become redundant when we add the new 'entry' to the end of
336 // the fEntries list. We also need to check if the new entry needs to be added
337 // at all because the trigger domain might already not contain those entries.
338 // Lastly, some intersection entries might need to be added to patch up existing
339 // inclusive trigger domain entries (rules / patterns).
340 for (Int_t i = 0; i < count; i++)
341 {
0a76630e 342 AliHLTDomainEntry* ientry = static_cast<AliHLTDomainEntry*>(fEntries[i]);
1b9a175e 343 if (ientry->Inclusive())
344 {
345 if (ientry->SubsetOf(entry))
346 {
0a76630e 347 ientry->SetBit(14, true); // mark for removal.
1b9a175e 348 }
349 else if (entry.SubsetOf(*ientry))
350 {
351 addToExcludeSet = true;
352 }
353 else if (ientry->IntersectWith(entry, intersect))
354 {
355 new (fEntries[fEntries.GetEntriesFast()]) AliHLTDomainEntry(kTRUE, intersect);
356 }
357 }
358 else
359 {
360 if (entry.SubsetOf(*ientry))
361 {
362 addToExcludeSet = false;
363 }
364 else if (ientry->SubsetOf(entry))
365 {
0a76630e 366 ientry->SetBit(14, true); // mark for removal.
1b9a175e 367 }
368 }
369 }
370
0a76630e 371 // Check if we need to add the new entry.
1b9a175e 372 if (addToExcludeSet)
373 {
0a76630e 374 MarkForDeletionSubsetsOf(entry, count);
1b9a175e 375 new (fEntries[fEntries.GetEntriesFast()]) AliHLTDomainEntry(kTRUE, entry);
376 }
0a76630e 377 RemoveMarkedEntries();
1b9a175e 378}
379
380
381void AliHLTTriggerDomain::Remove(const AliHLTComponentDataType& datatype)
382{
383 // Removes the domain entries that have the given data type from the trigger domain.
384 // See header file for more details.
385
386 Remove(AliHLTDomainEntry(datatype));
387}
388
389
390void AliHLTTriggerDomain::Remove(const char* blocktype, const char* origin)
391{
392 // Removes the domain entries that have the given data type and origin from the
393 // trigger domain.
394 // See header file for more details.
395
396 Remove(AliHLTDomainEntry(blocktype, origin));
397}
398
399
400void AliHLTTriggerDomain::Remove(const AliHLTComponentDataType& datatype, UInt_t spec)
401{
402 // Removes the domain entries that have the given data type and data block
403 // specification bits from the trigger domain.
404 // See header file for more details.
405
406 Remove(AliHLTDomainEntry(datatype, spec));
407}
408
409
410void AliHLTTriggerDomain::Remove(const char* blocktype, const char* origin, UInt_t spec)
411{
412 // Removes the domain entries that have the given data type, origin and data
413 // block specification bits from the trigger domain.
414 // See header file for more details.
415
416 Remove(AliHLTDomainEntry(blocktype, origin, spec));
417}
418
419
420bool AliHLTTriggerDomain::Contains(const AliHLTDomainEntry& entry) const
421{
422 // Checks to see if the given domain entry is part of the trigger domain set.
423 // See header file for more details.
424
425 // Simply go through the whole list of fEntries and for each entry see if the
426 // given domain entry 'entry' being checked matches. If there is a match then
427 // update the result depending on the entry type. i.e. set to false if the entry
428 // in fEntries is an exclusion and set to true if it is an inclusion.
429 bool result = false;
430 for (Int_t i = 0; i < fEntries.GetEntriesFast(); i++)
431 {
432 const AliHLTDomainEntry* ientry = static_cast<const AliHLTDomainEntry*>(fEntries[i]);
433 if (ientry->Inclusive())
434 {
435 if (*ientry == entry) result = true;
436 }
437 else
438 {
439 if (entry.SubsetOf(*ientry)) result = false;
440 }
441 }
442 return result;
443}
444
445
446bool AliHLTTriggerDomain::IncludeInReadout(const AliHLTComponentBlockData* block) const
447{
448 // Checks to see if the given data block is part of the trigger domain set and
449 // should be readout.
450 // See header file for more details.
451
452 // Same algorithm as for Contains() but applied directly to the data block
453 // descriptor structure.
454 AliHLTDomainEntry blockEntry(block->fDataType, block->fSpecification);
455 bool result = false;
456 for (Int_t i = 0; i < fEntries.GetEntriesFast(); i++)
457 {
458 const AliHLTDomainEntry* entry = static_cast<const AliHLTDomainEntry*>(fEntries[i]);
459 if (entry->Inclusive())
460 {
461 if (*entry == block) result = true;
462 }
463 else
464 {
465 if (blockEntry.SubsetOf(*entry)) result = false;
466 }
467 }
468 return result;
469}
470
471
472void AliHLTTriggerDomain::Clear(Option_t* option)
473{
474 // Clears the trigger domain (Removes all entries).
475
476 fEntries.Clear(option);
477}
478
479
480void AliHLTTriggerDomain::Print(Option_t* /*option*/) const
481{
482 // Prints the trigger domain entries in the order that they are applied.
483 // See header file for more details.
484
485 cout << "Trigger domain rules (applied in order of first to last):" << endl;
486 for (Int_t i = 0; i < fEntries.GetEntriesFast(); i++)
487 {
488 const AliHLTDomainEntry* entry = static_cast<const AliHLTDomainEntry*>( fEntries[i] );
489 if (entry->Inclusive())
490 {
491 cout << "Include ";
492 }
493 else
494 {
495 cout << "Exclude ";
496 }
497 entry->Print();
498 }
499 if (fEntries.GetEntriesFast() == 0)
500 {
501 cout << "(empty)" << endl;
502 }
503}
504
505
506AliHLTTriggerDomain& AliHLTTriggerDomain::operator = (const AliHLTTriggerDomain& domain)
507{
508 // Assignment operator performs a deep copy.
509 // See header file for more details.
510
511 if (this == &domain) return *this;
512 TObject::operator = (domain);
513 fEntries.Clear();
514 for (Int_t i = 0; i < domain.fEntries.GetEntriesFast(); i++)
515 {
516 const AliHLTDomainEntry* entry = static_cast<const AliHLTDomainEntry*>( domain.fEntries[i] );
517 new (fEntries[fEntries.GetEntriesFast()]) AliHLTDomainEntry(*entry);
518 }
519 return *this;
520}
521
522
523AliHLTTriggerDomain& AliHLTTriggerDomain::operator |= (const AliHLTTriggerDomain& domain)
524{
525 // This operator performs the set union.
526 // See header file for more details.
527
528 // Note that we partition the fEntries array into 3 regions for this calculation.
529 // - 0..entriesCount-1 : contains the initial entries of this trigger domain.
530 // - entriesCount..startOfIntersects-1 : is space reserved for the new entries
531 // from 'domain'.
532 // - startOfIntersects..fEntries.GetEntriesFast()-1 : This will grow as we add
533 // all the new domain intersections created during the calculation.
534 //
535 // Get the number of entries now before we start adding more entries from 'domain'.
536 Int_t count = fEntries.GetEntriesFast();
537 // Mark the start location for new intersection entries.
538 Int_t startOfIntersects = count + domain.fEntries.GetEntriesFast();
539 Int_t newIndex = startOfIntersects;
540
541 // Allocate and initialise a single block of memory so that we do not call new twice.
542 bool* buffer = new bool[startOfIntersects];
543 for (Int_t i = 0; i < startOfIntersects; i++) buffer[i] = false;
544 bool* removeThisEntry = buffer;
545 bool* removeDomainEntry = buffer + count;
546
547 AliHLTDomainEntry intersect;
548
549 // The idea behind this algorithm is that we need to add all inclusion domain
550 // entries from 'domain' to this object that will not be redundant, but for
551 // the exclusion entries we patch the fEntries rule set by adding the appropriate
552 // intersections to the end of fEntries.
553 for (Int_t i = 0; i < domain.fEntries.GetEntriesFast(); i++)
554 {
555 const AliHLTDomainEntry* newEntry = static_cast<const AliHLTDomainEntry*>( domain.fEntries[i] );
556 for (Int_t j = 0; j < count; j++)
557 {
558 const AliHLTDomainEntry* currentEntry = static_cast<const AliHLTDomainEntry*>( fEntries[j] );
559 if (currentEntry->Inclusive() and newEntry->Inclusive())
560 {
561 // If either entry is a subset of the other then we do not need to add
562 // both, so make sure to remove the one that is redundant.
563 if (newEntry->SubsetOf(*currentEntry))
564 {
565 removeDomainEntry[i] = true;
566 }
567 else if (currentEntry->SubsetOf(*newEntry))
568 {
569 removeThisEntry[j] = true;
570 }
571 }
572 else
573 {
574 if (newEntry->IntersectWith(*currentEntry, intersect))
575 {
576 // We can remove all intersections that were already added that will
577 // become redundant when this intersection is added to fEntries.
578 MarkForDeletionSubsetsOf(intersect, startOfIntersects);
579
580 // Make the new intersection entry an exclusion if the newEntry and
581 // currentEntry flags are the same.
582 bool exclude = newEntry->Exclusive() == currentEntry->Exclusive();
583 new (fEntries[newIndex++]) AliHLTDomainEntry(exclude, intersect);
584
585 // We can also remove entries that are subsets of another entry in the
586 // opposite list, since they will be redundant when everything is merged
587 // together. For example, remove entry x from fEntries if it is a subset
588 // of entry y in domain.fEntries.
589 if (currentEntry->IdenticalTo(intersect)) removeThisEntry[j] = true;
590 if (newEntry->IdenticalTo(intersect)) removeDomainEntry[i] = true;
591 }
592 }
593 }
594 }
595
596 MergeEntries(removeThisEntry, count, removeDomainEntry, startOfIntersects, domain);
597 delete [] buffer;
598 Optimise();
599 return *this;
600}
601
602
603AliHLTTriggerDomain& AliHLTTriggerDomain::operator ^= (const AliHLTTriggerDomain& domain)
604{
605 // This operator performs the set union, less the set intersect (something like and xor).
606 // See header file for more details.
607
608 // Note that we partition the fEntries array into 3 regions for this calculation.
609 // - 0..entriesCount-1 : contains the initial entries of this trigger domain.
610 // - entriesCount..startOfIntersects-1 : is space reserved for the new entries
611 // from 'domain'.
612 // - startOfIntersects..fEntries.GetEntriesFast()-1 : This will grow as we add
613 // all the new domain intersections created during the calculation.
614 //
615 // Get the number of entries now before we start adding more entries from 'domain'.
616 Int_t count = fEntries.GetEntriesFast();
617 // Mark the start location for new intersection entries.
618 Int_t startOfIntersects = count + domain.fEntries.GetEntriesFast();
619 Int_t newIndex = startOfIntersects;
620
621 // Allocate and initialise a single block of memory so that we do not call new twice.
622 bool* buffer = new bool[startOfIntersects];
623 for (Int_t i = 0; i < startOfIntersects; i++) buffer[i] = false;
624 bool* removeThisEntry = buffer;
625 bool* removeDomainEntry = buffer + count;
626
627 AliHLTDomainEntry intersect;
628
629 // This algorithm is similar to the case for the set union (operator |=), except
630 // that we make sure to remove from the trigger domain all parts where the entries
631 // from fEntries and domain.fEntries intersect.
632 // This is done by adding the intersections to the end of fEntries such that they
633 // effectively remove those overlapping trigger domain entries when calculating
634 // IncludeInReadout() or Contains().
635 for (Int_t i = 0; i < domain.fEntries.GetEntriesFast(); i++)
636 {
637 const AliHLTDomainEntry* newEntry = static_cast<const AliHLTDomainEntry*>( domain.fEntries[i] );
638 for (Int_t j = 0; j < count; j++)
639 {
640 const AliHLTDomainEntry* currentEntry = static_cast<const AliHLTDomainEntry*>( fEntries[j] );
641 if (newEntry->IntersectWith(*currentEntry, intersect))
642 {
643 // We can remove all intersections that were already added that will
644 // become redundant when this intersection is added to fEntries.
645 MarkForDeletionSubsetsOf(intersect, startOfIntersects);
646
647 // Make the new intersection entry an exclusion if the newEntry and
648 // currentEntry flags are the same.
649 bool exclude = newEntry->Exclusive() == currentEntry->Exclusive();
650 new (fEntries[newIndex++]) AliHLTDomainEntry(exclude, intersect);
651
652 // We can also remove entries that are subsets of another entry in the
653 // opposite list, since they will be redundant when everything is merged
654 // together. For example, remove entry x from fEntries if it is a subset
655 // of entry y in domain.fEntries.
656 if (currentEntry->IdenticalTo(intersect)) removeThisEntry[j] = true;
657 if (newEntry->IdenticalTo(intersect)) removeDomainEntry[i] = true;
658 }
659 }
660 }
661
662 MergeEntries(removeThisEntry, count, removeDomainEntry, startOfIntersects, domain);
663 delete [] buffer;
664 Optimise();
665 return *this;
666}
667
668
669AliHLTTriggerDomain& AliHLTTriggerDomain::operator -= (const AliHLTTriggerDomain& domain)
670{
671 // This operator performs the set difference.
672 // See header file for more details.
673
674 // Mark the number of entries in fEntries now before we start adding more
675 // entries from 'domain' or intersections.
676 Int_t startOfIntersects = fEntries.GetEntriesFast();
677 Int_t newIndex = startOfIntersects;
678
679 AliHLTDomainEntry intersect;
680
681 // To compute the set difference we need to remove all all parts that overlap
682 // with 'domain'. i.e. we need to find all the intersects between the domain
683 // entries in fEntries and those in domain.fEntries, and add the intersects
684 // to the fEntries list, such that they will cancel or remove the overlapping
685 // parts of the two trigger domains.
686 for (Int_t i = 0; i < domain.fEntries.GetEntriesFast(); i++)
687 {
688 const AliHLTDomainEntry* checkEntry = static_cast<const AliHLTDomainEntry*>( domain.fEntries[i] );
689 if (checkEntry->Inclusive())
690 {
691 // For inclusive entries we need to find the overlaps with the inclusive
692 // entries in fEntries and add exclusive entries that will remove that
693 // part of the trigger domain set.
694 for (Int_t j = 0; j < startOfIntersects; j++)
695 {
696 AliHLTDomainEntry* currentEntry = static_cast<AliHLTDomainEntry*>( fEntries[j] );
697
698 // We only need to consider the case where both entries are inclusive,
699 // since an exclusion in fEntries already eliminates those data blocks
700 // from the trigger domain set.
701 if (currentEntry->Exclusive()) continue;
702
703 if (checkEntry->IntersectWith(*currentEntry, intersect))
704 {
705 // We can remove all intersections that were already added that will
706 // become redundant when this intersection is added to fEntries.
707 MarkForDeletionSubsetsOf(intersect, startOfIntersects);
708
709 new (fEntries[newIndex++]) AliHLTDomainEntry(kTRUE, intersect);
710 if (currentEntry->IdenticalTo(intersect))
711 {
712 currentEntry->SetBit(14, true);
713 }
714 }
715 }
716 }
717 else
718 {
719 // For an exclusive entry in 'domain' we need to find the intersections with
720 // all of fEntries and re-apply these with the same exclude flags.
721 for (Int_t j = 0; j < startOfIntersects; j++)
722 {
723 AliHLTDomainEntry* currentEntry = static_cast<AliHLTDomainEntry*>( fEntries[j] );
724 if (checkEntry->IntersectWith(*currentEntry, intersect))
725 {
726 // We can remove all intersections that were already added that will
727 // become redundant when this intersection is added to fEntries.
728 MarkForDeletionSubsetsOf(intersect, startOfIntersects);
729
730 new (fEntries[newIndex++]) AliHLTDomainEntry(currentEntry->Exclusive(), intersect);
731 }
732 }
733 }
734 }
735
736 RemoveMarkedEntries();
737 Optimise();
738 return *this;
739}
740
741
742AliHLTTriggerDomain AliHLTTriggerDomain::operator ~ () const
743{
744 // Performs a set complement of the trigger domain.
745
746 // The set complement is calculated by creating a new trigger domain which
747 // accepts all possible data blocks, and then apply all the trigger domain
748 // entries (rules / patterns) from top to bottom, but apply them with the
749 // opposite meaning. For example, this->fEntries contains an inclusive domain
750 // entry then remove it from the new trigger domain 'result', but if it is
751 // an exclusion then add it.
752 AliHLTTriggerDomain result;
753 result.Add(kAliHLTAnyDataType);
754 for (Int_t i = 0; i < fEntries.GetEntriesFast(); i++)
755 {
756 const AliHLTDomainEntry* entry = static_cast<const AliHLTDomainEntry*>( fEntries[i] );
757 if (entry->Inclusive())
758 {
759 result.Remove(*entry);
760 }
761 else
762 {
763 result.Add(*entry);
764 }
765 }
766 return result;
767}
768
769
770AliHLTTriggerDomain AliHLTTriggerDomain::operator & (const AliHLTTriggerDomain& domain) const
771{
772 // This operator finds the set intersect.
773 // See header file for more details.
774
775 AliHLTTriggerDomain result;
776 Int_t newIndex = 0;
777 AliHLTDomainEntry intersect;
778
779 // To find the set intersect we need to compare each entry in 'domain' to those
780 // of fEntries. For each inclusive entry in 'domain' we need to add to the result
781 // the intersect between it and each entry of fEntries, with the same exclude flag
782 // value as the domain entry from fEntries.
783 // However, in principle, for the exclusion entries in 'domain' we just add them
784 // to the result, since those entries do not form part of the 'domain' trigger
785 // domain set, so they should not form part of the result (remember any data block
786 // must be contained in both trigger domains for a set intersect).
787 // In actual fact we just add the intersect of the exclusion entries in 'domain'
788 // with those of fEntries to the result. This has the same overall effect, but
789 // makes sure that all exclusion entries are always subsets of inclusion entries.
790 for (Int_t i = 0; i < domain.fEntries.GetEntriesFast(); i++)
791 {
792 const AliHLTDomainEntry* checkEntry = static_cast<const AliHLTDomainEntry*>( domain.fEntries[i] );
793 if (checkEntry->Inclusive())
794 {
795 for (Int_t j = 0; j < fEntries.GetEntriesFast(); j++)
796 {
797 AliHLTDomainEntry* currentEntry = static_cast<AliHLTDomainEntry*>( fEntries[j] );
798 if (checkEntry->IntersectWith(*currentEntry, intersect))
799 {
800 // We can remove all entries that were already added to the result that
801 // will become redundent because they are subsets of the new entry.
802 result.MarkForDeletionSubsetsOf(intersect, 0);
803
804 new (result.fEntries[newIndex++]) AliHLTDomainEntry(currentEntry->Exclusive(), intersect);
805 }
806 }
807 }
808 else
809 {
810 for (Int_t j = 0; j < fEntries.GetEntriesFast(); j++)
811 {
812 AliHLTDomainEntry* currentEntry = static_cast<AliHLTDomainEntry*>( fEntries[j] );
813 if (checkEntry->IntersectWith(*currentEntry, intersect))
814 {
815 // We can remove all entries that were already added to the result that
816 // will become redundant because they are subsets of the new entry.
817 result.MarkForDeletionSubsetsOf(intersect, 0);
818
819 new (result.fEntries[newIndex++]) AliHLTDomainEntry(kTRUE, intersect);
820 }
821 }
822 }
823 }
824
825 result.RemoveMarkedEntries();
826 result.Optimise();
827 return result;
828}
829
830
52f67e50 831AliHLTTriggerDomain::operator AliHLTReadoutList () const
832{
833 // Typecast operator which constructs a readout list from the trigger domain.
834
835 AliHLTReadoutList result;
836 for (Int_t deti = 0; deti < AliDAQ::kNDetectors; deti++)
837 {
838 for (Int_t i = 0; i < AliDAQ::NumberOfDdls(deti); i++)
839 {
840 Int_t ddlId = AliDAQ::DdlID(deti, i);
841 if (Contains(AliHLTDomainEntry("DAQRDOUT", AliDAQ::OnlineName(deti), ddlId)))
842 {
843 result.EnableDDLBit(ddlId);
844 }
845 }
846 }
847 return result;
848}
849
850
1b9a175e 851void AliHLTTriggerDomain::MergeEntries(
852 const bool* removeThisEntry, Int_t entriesCount,
853 const bool* removeDomainEntry, Int_t startOfIntersects,
854 const AliHLTTriggerDomain& domain
855 )
856{
857 // Merges the entries in this trigger domain with the ones in 'domain', while
858 // removing all entries that were marked for removal.
859 // See header file for more information.
860
861 bool anythingRemoved = false;
862
863 // Remember this method is used at the end of the calculation of the binary operators
864 // and that fEntries is expected to be partitioned into 3 regions.
865 // - 0..entriesCount-1 : contains the original (initial) entries of this trigger domain.
866 // - entriesCount..startOfIntersects-1 : is space reserved for the new entries
867 // from the given trigger domain 'domain' being processed.
868 // - startOfIntersects..fEntries.GetEntriesFast()-1 : contains all new domain entry
869 // intersection created and added to fEntries.
870 //
871 // First we need to remove all entries marked for removal from the original entries.
872 for (Int_t i = 0; i < entriesCount; i++)
873 {
874 if (removeThisEntry[i])
875 {
876 fEntries.RemoveAt(i);
877 anythingRemoved = true;
878 }
879 }
880
881 // Now we copy over all the new entries from 'domain' which were not marked for removal
882 // and indicate anythingRemoved = true since there will now be gaps in the clones array
883 // that need to be compressed away later.
884 for (Int_t i = 0; i < domain.fEntries.GetEntriesFast(); i++)
885 {
886 if (removeDomainEntry[i])
887 {
888 anythingRemoved = true;
889 }
890 else
891 {
892 const AliHLTDomainEntry* newEntry = static_cast<const AliHLTDomainEntry*>( domain.fEntries[i] );
893 new (fEntries[entriesCount+i]) AliHLTDomainEntry(*newEntry);
894 }
895 }
896
897 // Finally remove all new intersection entries that were marked for removal by
898 // the MarkForDeletionSubsetsOf method.
899 for (Int_t i = startOfIntersects; i < fEntries.GetEntriesFast(); i++)
900 {
901 const AliHLTDomainEntry* ientry = static_cast<const AliHLTDomainEntry*>( fEntries[i] );
902 if (ientry->TestBit(14))
903 {
904 fEntries.RemoveAt(i);
905 anythingRemoved = true;
906 }
907 }
908 if (anythingRemoved) fEntries.Compress();
909}
910
911
912void AliHLTTriggerDomain::MarkForDeletionSubsetsOf(const AliHLTDomainEntry& entry, Int_t min)
913{
914 // Marks for deletion all the entries in this trigger domain that are subsets
915 // of the given entry.
916 // See header file for more information.
917
918 AliHLTDomainEntry intersect;
919 for (Int_t i = min; i < fEntries.GetEntriesFast(); i++)
920 {
921 AliHLTDomainEntry* ientry = static_cast<AliHLTDomainEntry*>( fEntries[i] );
922 if (ientry->TestBit(14)) continue;
923 if (ientry->SubsetOf(entry))
924 {
925 ientry->SetBit(14, true);
926 }
927 }
928}
929
930
931void AliHLTTriggerDomain::RemoveMarkedEntries()
932{
0a76630e 933 // Removes all entries in this trigger domain which were marked for removal.
1b9a175e 934 // See header file for more information.
935
936 bool anythingRemoved = false;
937 for (Int_t i = 0; i < fEntries.GetEntriesFast(); i++)
938 {
939 const AliHLTDomainEntry* ientry = static_cast<const AliHLTDomainEntry*>( fEntries[i] );
940 if (ientry->TestBit(14))
941 {
942 fEntries.RemoveAt(i);
943 anythingRemoved = true;
944 }
945 }
946 if (anythingRemoved) fEntries.Compress();
947}
948
949
950void AliHLTTriggerDomain::Optimise()
951{
952 // Removes redundant trigger domain entries from the trigger domain.
953 // See header file for more information.
954
955 AliHLTDomainEntry intersect;
956
957 // Check that the first entry is not and exclusion which would be redundent.
958 if (fEntries.GetEntriesFast() == 0) return;
959 AliHLTDomainEntry* firstEntry = static_cast<AliHLTDomainEntry*>( fEntries[0] );
960 if (firstEntry->Exclusive()) firstEntry->SetBit(14, true);
961
962 for (Int_t i = 1; i < fEntries.GetEntriesFast(); i++)
963 {
964 AliHLTDomainEntry* ientry = static_cast<AliHLTDomainEntry*>( fEntries[i] );
965
966 // For the i'th entry in fEntries, compare it in reverse order with all other
967 // entries that are before it and look for redundant ones, i.e. that are subsets
968 // of the i'th entry.
969 for (Int_t j = i-1; j >= 0; j--)
970 {
971 AliHLTDomainEntry* jentry = static_cast<AliHLTDomainEntry*>( fEntries[j] );
972 if (jentry->TestBit(14)) continue;
973 // Find entries that intersect
974 if (jentry->SubsetOf(*ientry))
975 {
976 // jentry is a subset of ientry so it is redundant because for all values
977 // ientry will override jentry when calling IncludeInReadout.
978 jentry->SetBit(14, true);
979 }
980 else if (*ientry == *jentry)
981 {
982 // If intersecting entries have opposite exclude flags then search no further,
983 // we know that we will need this entry for correct behaviour of IncludeInReadout.
984 if (ientry->Inclusive() == jentry->Exclusive()) goto processNextEntry;
985
986 if (ientry->SubsetOf(*jentry))
987 {
988 ientry->SetBit(14, true);
989 goto processNextEntry;
990 }
991 }
992 }
993
994 // If we got to this point then we hit the top of the trigger domain rules
995 // (pattern matching) list without hitting any and overlapping entries.
996 // So now we need to check if ientry is an exclusion. If it is, then it is
997 // redundant and we can mark it for removal.
998 if (ientry->Exclusive()) ientry->SetBit(14, true);
999
1000 processNextEntry: ;
1001 }
1002
1003 RemoveMarkedEntries();
1004}
1005