Adding trigger domain and trigger decision classes. AliHLTTrigger now produces an...
[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"
27#include "Riostream.h"
28
29ClassImp(AliHLTTriggerDomain)
30
31
32AliHLTTriggerDomain::AliHLTTriggerDomain() :
33 TObject(), fEntries(AliHLTDomainEntry::Class(), 10)
34{
35 // Default constructor.
36}
37
38
39AliHLTTriggerDomain::AliHLTTriggerDomain(const AliHLTTriggerDomain& domain) :
40 TObject(domain),
41 fEntries(AliHLTDomainEntry::Class(), domain.fEntries.GetEntriesFast())
42{
43 // Copy constructor performs a deep copy.
44 // See header file for more details.
45
46 for (Int_t i = 0; i < domain.fEntries.GetEntriesFast(); i++)
47 {
48 const AliHLTDomainEntry* entry = static_cast<const AliHLTDomainEntry*>( domain.fEntries[i] );
49 new (fEntries[fEntries.GetEntriesFast()]) AliHLTDomainEntry(*entry);
50 }
51}
52
53
54AliHLTTriggerDomain::~AliHLTTriggerDomain()
55{
56 // Default destructor.
57}
58
59
60void AliHLTTriggerDomain::Add(const AliHLTDomainEntry& entry)
61{
62 // Adds a new domain entry to the trigger domain.
63 // See header file for more details.
64
65 AliHLTDomainEntry intersect;
66 bool anythingRemoved = false;
67 bool alreadyInSet = false;
68
69 // Get the initial size of the fEntries array since we might add things to the
70 // end during the calculation.
71 Int_t count = fEntries.GetEntriesFast();
72
73 // Go through each entry that is already in fEntries and see if we can remove
74 // it because it will become redundant, or if we need to patch exclusion entries
75 // by adding inclusive intersects, or if we do not even need to add the new entry
76 // because it is already part of the trigger domain.
77 for (Int_t i = 0; i < count; i++)
78 {
79 const AliHLTDomainEntry* ientry = static_cast<const AliHLTDomainEntry*>(fEntries[i]);
80 if (ientry->Inclusive())
81 {
82 if (entry.SubsetOf(*ientry))
83 {
84 alreadyInSet = true;
85 }
86 else if (ientry->SubsetOf(entry))
87 {
88 fEntries.RemoveAt(i);
89 anythingRemoved = true;
90 }
91 }
92 else
93 {
94 if (ientry->SubsetOf(entry))
95 {
96 fEntries.RemoveAt(i);
97 anythingRemoved = true;
98 }
99 else if (entry.SubsetOf(*ientry))
100 {
101 alreadyInSet = false;
102 }
103 else if (ientry->IntersectWith(entry, intersect))
104 {
105 new (fEntries[fEntries.GetEntriesFast()]) AliHLTDomainEntry(kFALSE, intersect);
106 alreadyInSet = true;
107 }
108 }
109 }
110
111 // Check if we need to compress the array and if we need to add the new entry.
112 if (anythingRemoved) fEntries.Compress();
113 if (not alreadyInSet)
114 {
115 new (fEntries[fEntries.GetEntriesFast()]) AliHLTDomainEntry(kFALSE, entry);
116 }
117}
118
119
120void AliHLTTriggerDomain::Add(const AliHLTComponentDataType& datatype)
121{
122 // Adds a new domain entry with the given data type to the trigger domain.
123 // But the data block specification is set to the any matching wild card.
124 // See header file for more details.
125
126 Add(AliHLTDomainEntry(datatype));
127}
128
129
130void AliHLTTriggerDomain::Add(const char* blocktype, const char* origin)
131{
132 // Adds a new domain entry with the given data type and origin to the trigger domain.
133 // But the data block specification is set to the any matching wild card.
134 // See header file for more details.
135
136 Add(AliHLTDomainEntry(blocktype, origin));
137}
138
139
140void AliHLTTriggerDomain::Add(const AliHLTComponentDataType& datatype, UInt_t spec)
141{
142 // Adds a new domain entry to the trigger domain with the data type and data block
143 // specification bits.
144 // See header file for more details.
145
146 Add(AliHLTDomainEntry(datatype, spec));
147}
148
149
150void AliHLTTriggerDomain::Add(const char* blocktype, const char* origin, UInt_t spec)
151{
152 // Adds a new domain entry to the trigger domain with the given data type, origin
153 // and data block specification bits.
154 // See header file for more details.
155
156 Add(AliHLTDomainEntry(blocktype, origin, spec));
157}
158
159
160void AliHLTTriggerDomain::Remove(const AliHLTDomainEntry& entry)
161{
162 // Removes the given domain entry from the trigger domain.
163 // See header file for more details.
164
165 AliHLTDomainEntry intersect;
166 bool anythingRemoved = false;
167 bool addToExcludeSet = false;
168
169 // Get the initial size of the fEntries array since we might add things to the
170 // end during the calculation.
171 Int_t count = fEntries.GetEntriesFast();
172
173 // We need to go through all existing entries and see if they need to be removed
174 // because they would become redundant when we add the new 'entry' to the end of
175 // the fEntries list. We also need to check if the new entry needs to be added
176 // at all because the trigger domain might already not contain those entries.
177 // Lastly, some intersection entries might need to be added to patch up existing
178 // inclusive trigger domain entries (rules / patterns).
179 for (Int_t i = 0; i < count; i++)
180 {
181 const AliHLTDomainEntry* ientry = static_cast<const AliHLTDomainEntry*>(fEntries[i]);
182 if (ientry->Inclusive())
183 {
184 if (ientry->SubsetOf(entry))
185 {
186 fEntries.RemoveAt(i);
187 anythingRemoved = true;
188 }
189 else if (entry.SubsetOf(*ientry))
190 {
191 addToExcludeSet = true;
192 }
193 else if (ientry->IntersectWith(entry, intersect))
194 {
195 new (fEntries[fEntries.GetEntriesFast()]) AliHLTDomainEntry(kTRUE, intersect);
196 }
197 }
198 else
199 {
200 if (entry.SubsetOf(*ientry))
201 {
202 addToExcludeSet = false;
203 }
204 else if (ientry->SubsetOf(entry))
205 {
206 fEntries.RemoveAt(i);
207 anythingRemoved = true;
208 }
209 }
210 }
211
212 // Check if we need to compress the array and if we need to add the new entry.
213 if (anythingRemoved) fEntries.Compress();
214 if (addToExcludeSet)
215 {
216 new (fEntries[fEntries.GetEntriesFast()]) AliHLTDomainEntry(kTRUE, entry);
217 }
218}
219
220
221void AliHLTTriggerDomain::Remove(const AliHLTComponentDataType& datatype)
222{
223 // Removes the domain entries that have the given data type from the trigger domain.
224 // See header file for more details.
225
226 Remove(AliHLTDomainEntry(datatype));
227}
228
229
230void AliHLTTriggerDomain::Remove(const char* blocktype, const char* origin)
231{
232 // Removes the domain entries that have the given data type and origin from the
233 // trigger domain.
234 // See header file for more details.
235
236 Remove(AliHLTDomainEntry(blocktype, origin));
237}
238
239
240void AliHLTTriggerDomain::Remove(const AliHLTComponentDataType& datatype, UInt_t spec)
241{
242 // Removes the domain entries that have the given data type and data block
243 // specification bits from the trigger domain.
244 // See header file for more details.
245
246 Remove(AliHLTDomainEntry(datatype, spec));
247}
248
249
250void AliHLTTriggerDomain::Remove(const char* blocktype, const char* origin, UInt_t spec)
251{
252 // Removes the domain entries that have the given data type, origin and data
253 // block specification bits from the trigger domain.
254 // See header file for more details.
255
256 Remove(AliHLTDomainEntry(blocktype, origin, spec));
257}
258
259
260bool AliHLTTriggerDomain::Contains(const AliHLTDomainEntry& entry) const
261{
262 // Checks to see if the given domain entry is part of the trigger domain set.
263 // See header file for more details.
264
265 // Simply go through the whole list of fEntries and for each entry see if the
266 // given domain entry 'entry' being checked matches. If there is a match then
267 // update the result depending on the entry type. i.e. set to false if the entry
268 // in fEntries is an exclusion and set to true if it is an inclusion.
269 bool result = false;
270 for (Int_t i = 0; i < fEntries.GetEntriesFast(); i++)
271 {
272 const AliHLTDomainEntry* ientry = static_cast<const AliHLTDomainEntry*>(fEntries[i]);
273 if (ientry->Inclusive())
274 {
275 if (*ientry == entry) result = true;
276 }
277 else
278 {
279 if (entry.SubsetOf(*ientry)) result = false;
280 }
281 }
282 return result;
283}
284
285
286bool AliHLTTriggerDomain::IncludeInReadout(const AliHLTComponentBlockData* block) const
287{
288 // Checks to see if the given data block is part of the trigger domain set and
289 // should be readout.
290 // See header file for more details.
291
292 // Same algorithm as for Contains() but applied directly to the data block
293 // descriptor structure.
294 AliHLTDomainEntry blockEntry(block->fDataType, block->fSpecification);
295 bool result = false;
296 for (Int_t i = 0; i < fEntries.GetEntriesFast(); i++)
297 {
298 const AliHLTDomainEntry* entry = static_cast<const AliHLTDomainEntry*>(fEntries[i]);
299 if (entry->Inclusive())
300 {
301 if (*entry == block) result = true;
302 }
303 else
304 {
305 if (blockEntry.SubsetOf(*entry)) result = false;
306 }
307 }
308 return result;
309}
310
311
312void AliHLTTriggerDomain::Clear(Option_t* option)
313{
314 // Clears the trigger domain (Removes all entries).
315
316 fEntries.Clear(option);
317}
318
319
320void AliHLTTriggerDomain::Print(Option_t* /*option*/) const
321{
322 // Prints the trigger domain entries in the order that they are applied.
323 // See header file for more details.
324
325 cout << "Trigger domain rules (applied in order of first to last):" << endl;
326 for (Int_t i = 0; i < fEntries.GetEntriesFast(); i++)
327 {
328 const AliHLTDomainEntry* entry = static_cast<const AliHLTDomainEntry*>( fEntries[i] );
329 if (entry->Inclusive())
330 {
331 cout << "Include ";
332 }
333 else
334 {
335 cout << "Exclude ";
336 }
337 entry->Print();
338 }
339 if (fEntries.GetEntriesFast() == 0)
340 {
341 cout << "(empty)" << endl;
342 }
343}
344
345
346AliHLTTriggerDomain& AliHLTTriggerDomain::operator = (const AliHLTTriggerDomain& domain)
347{
348 // Assignment operator performs a deep copy.
349 // See header file for more details.
350
351 if (this == &domain) return *this;
352 TObject::operator = (domain);
353 fEntries.Clear();
354 for (Int_t i = 0; i < domain.fEntries.GetEntriesFast(); i++)
355 {
356 const AliHLTDomainEntry* entry = static_cast<const AliHLTDomainEntry*>( domain.fEntries[i] );
357 new (fEntries[fEntries.GetEntriesFast()]) AliHLTDomainEntry(*entry);
358 }
359 return *this;
360}
361
362
363AliHLTTriggerDomain& AliHLTTriggerDomain::operator |= (const AliHLTTriggerDomain& domain)
364{
365 // This operator performs the set union.
366 // See header file for more details.
367
368 // Note that we partition the fEntries array into 3 regions for this calculation.
369 // - 0..entriesCount-1 : contains the initial entries of this trigger domain.
370 // - entriesCount..startOfIntersects-1 : is space reserved for the new entries
371 // from 'domain'.
372 // - startOfIntersects..fEntries.GetEntriesFast()-1 : This will grow as we add
373 // all the new domain intersections created during the calculation.
374 //
375 // Get the number of entries now before we start adding more entries from 'domain'.
376 Int_t count = fEntries.GetEntriesFast();
377 // Mark the start location for new intersection entries.
378 Int_t startOfIntersects = count + domain.fEntries.GetEntriesFast();
379 Int_t newIndex = startOfIntersects;
380
381 // Allocate and initialise a single block of memory so that we do not call new twice.
382 bool* buffer = new bool[startOfIntersects];
383 for (Int_t i = 0; i < startOfIntersects; i++) buffer[i] = false;
384 bool* removeThisEntry = buffer;
385 bool* removeDomainEntry = buffer + count;
386
387 AliHLTDomainEntry intersect;
388
389 // The idea behind this algorithm is that we need to add all inclusion domain
390 // entries from 'domain' to this object that will not be redundant, but for
391 // the exclusion entries we patch the fEntries rule set by adding the appropriate
392 // intersections to the end of fEntries.
393 for (Int_t i = 0; i < domain.fEntries.GetEntriesFast(); i++)
394 {
395 const AliHLTDomainEntry* newEntry = static_cast<const AliHLTDomainEntry*>( domain.fEntries[i] );
396 for (Int_t j = 0; j < count; j++)
397 {
398 const AliHLTDomainEntry* currentEntry = static_cast<const AliHLTDomainEntry*>( fEntries[j] );
399 if (currentEntry->Inclusive() and newEntry->Inclusive())
400 {
401 // If either entry is a subset of the other then we do not need to add
402 // both, so make sure to remove the one that is redundant.
403 if (newEntry->SubsetOf(*currentEntry))
404 {
405 removeDomainEntry[i] = true;
406 }
407 else if (currentEntry->SubsetOf(*newEntry))
408 {
409 removeThisEntry[j] = true;
410 }
411 }
412 else
413 {
414 if (newEntry->IntersectWith(*currentEntry, intersect))
415 {
416 // We can remove all intersections that were already added that will
417 // become redundant when this intersection is added to fEntries.
418 MarkForDeletionSubsetsOf(intersect, startOfIntersects);
419
420 // Make the new intersection entry an exclusion if the newEntry and
421 // currentEntry flags are the same.
422 bool exclude = newEntry->Exclusive() == currentEntry->Exclusive();
423 new (fEntries[newIndex++]) AliHLTDomainEntry(exclude, intersect);
424
425 // We can also remove entries that are subsets of another entry in the
426 // opposite list, since they will be redundant when everything is merged
427 // together. For example, remove entry x from fEntries if it is a subset
428 // of entry y in domain.fEntries.
429 if (currentEntry->IdenticalTo(intersect)) removeThisEntry[j] = true;
430 if (newEntry->IdenticalTo(intersect)) removeDomainEntry[i] = true;
431 }
432 }
433 }
434 }
435
436 MergeEntries(removeThisEntry, count, removeDomainEntry, startOfIntersects, domain);
437 delete [] buffer;
438 Optimise();
439 return *this;
440}
441
442
443AliHLTTriggerDomain& AliHLTTriggerDomain::operator ^= (const AliHLTTriggerDomain& domain)
444{
445 // This operator performs the set union, less the set intersect (something like and xor).
446 // See header file for more details.
447
448 // Note that we partition the fEntries array into 3 regions for this calculation.
449 // - 0..entriesCount-1 : contains the initial entries of this trigger domain.
450 // - entriesCount..startOfIntersects-1 : is space reserved for the new entries
451 // from 'domain'.
452 // - startOfIntersects..fEntries.GetEntriesFast()-1 : This will grow as we add
453 // all the new domain intersections created during the calculation.
454 //
455 // Get the number of entries now before we start adding more entries from 'domain'.
456 Int_t count = fEntries.GetEntriesFast();
457 // Mark the start location for new intersection entries.
458 Int_t startOfIntersects = count + domain.fEntries.GetEntriesFast();
459 Int_t newIndex = startOfIntersects;
460
461 // Allocate and initialise a single block of memory so that we do not call new twice.
462 bool* buffer = new bool[startOfIntersects];
463 for (Int_t i = 0; i < startOfIntersects; i++) buffer[i] = false;
464 bool* removeThisEntry = buffer;
465 bool* removeDomainEntry = buffer + count;
466
467 AliHLTDomainEntry intersect;
468
469 // This algorithm is similar to the case for the set union (operator |=), except
470 // that we make sure to remove from the trigger domain all parts where the entries
471 // from fEntries and domain.fEntries intersect.
472 // This is done by adding the intersections to the end of fEntries such that they
473 // effectively remove those overlapping trigger domain entries when calculating
474 // IncludeInReadout() or Contains().
475 for (Int_t i = 0; i < domain.fEntries.GetEntriesFast(); i++)
476 {
477 const AliHLTDomainEntry* newEntry = static_cast<const AliHLTDomainEntry*>( domain.fEntries[i] );
478 for (Int_t j = 0; j < count; j++)
479 {
480 const AliHLTDomainEntry* currentEntry = static_cast<const AliHLTDomainEntry*>( fEntries[j] );
481 if (newEntry->IntersectWith(*currentEntry, intersect))
482 {
483 // We can remove all intersections that were already added that will
484 // become redundant when this intersection is added to fEntries.
485 MarkForDeletionSubsetsOf(intersect, startOfIntersects);
486
487 // Make the new intersection entry an exclusion if the newEntry and
488 // currentEntry flags are the same.
489 bool exclude = newEntry->Exclusive() == currentEntry->Exclusive();
490 new (fEntries[newIndex++]) AliHLTDomainEntry(exclude, intersect);
491
492 // We can also remove entries that are subsets of another entry in the
493 // opposite list, since they will be redundant when everything is merged
494 // together. For example, remove entry x from fEntries if it is a subset
495 // of entry y in domain.fEntries.
496 if (currentEntry->IdenticalTo(intersect)) removeThisEntry[j] = true;
497 if (newEntry->IdenticalTo(intersect)) removeDomainEntry[i] = true;
498 }
499 }
500 }
501
502 MergeEntries(removeThisEntry, count, removeDomainEntry, startOfIntersects, domain);
503 delete [] buffer;
504 Optimise();
505 return *this;
506}
507
508
509AliHLTTriggerDomain& AliHLTTriggerDomain::operator -= (const AliHLTTriggerDomain& domain)
510{
511 // This operator performs the set difference.
512 // See header file for more details.
513
514 // Mark the number of entries in fEntries now before we start adding more
515 // entries from 'domain' or intersections.
516 Int_t startOfIntersects = fEntries.GetEntriesFast();
517 Int_t newIndex = startOfIntersects;
518
519 AliHLTDomainEntry intersect;
520
521 // To compute the set difference we need to remove all all parts that overlap
522 // with 'domain'. i.e. we need to find all the intersects between the domain
523 // entries in fEntries and those in domain.fEntries, and add the intersects
524 // to the fEntries list, such that they will cancel or remove the overlapping
525 // parts of the two trigger domains.
526 for (Int_t i = 0; i < domain.fEntries.GetEntriesFast(); i++)
527 {
528 const AliHLTDomainEntry* checkEntry = static_cast<const AliHLTDomainEntry*>( domain.fEntries[i] );
529 if (checkEntry->Inclusive())
530 {
531 // For inclusive entries we need to find the overlaps with the inclusive
532 // entries in fEntries and add exclusive entries that will remove that
533 // part of the trigger domain set.
534 for (Int_t j = 0; j < startOfIntersects; j++)
535 {
536 AliHLTDomainEntry* currentEntry = static_cast<AliHLTDomainEntry*>( fEntries[j] );
537
538 // We only need to consider the case where both entries are inclusive,
539 // since an exclusion in fEntries already eliminates those data blocks
540 // from the trigger domain set.
541 if (currentEntry->Exclusive()) continue;
542
543 if (checkEntry->IntersectWith(*currentEntry, intersect))
544 {
545 // We can remove all intersections that were already added that will
546 // become redundant when this intersection is added to fEntries.
547 MarkForDeletionSubsetsOf(intersect, startOfIntersects);
548
549 new (fEntries[newIndex++]) AliHLTDomainEntry(kTRUE, intersect);
550 if (currentEntry->IdenticalTo(intersect))
551 {
552 currentEntry->SetBit(14, true);
553 }
554 }
555 }
556 }
557 else
558 {
559 // For an exclusive entry in 'domain' we need to find the intersections with
560 // all of fEntries and re-apply these with the same exclude flags.
561 for (Int_t j = 0; j < startOfIntersects; j++)
562 {
563 AliHLTDomainEntry* currentEntry = static_cast<AliHLTDomainEntry*>( fEntries[j] );
564 if (checkEntry->IntersectWith(*currentEntry, intersect))
565 {
566 // We can remove all intersections that were already added that will
567 // become redundant when this intersection is added to fEntries.
568 MarkForDeletionSubsetsOf(intersect, startOfIntersects);
569
570 new (fEntries[newIndex++]) AliHLTDomainEntry(currentEntry->Exclusive(), intersect);
571 }
572 }
573 }
574 }
575
576 RemoveMarkedEntries();
577 Optimise();
578 return *this;
579}
580
581
582AliHLTTriggerDomain AliHLTTriggerDomain::operator ~ () const
583{
584 // Performs a set complement of the trigger domain.
585
586 // The set complement is calculated by creating a new trigger domain which
587 // accepts all possible data blocks, and then apply all the trigger domain
588 // entries (rules / patterns) from top to bottom, but apply them with the
589 // opposite meaning. For example, this->fEntries contains an inclusive domain
590 // entry then remove it from the new trigger domain 'result', but if it is
591 // an exclusion then add it.
592 AliHLTTriggerDomain result;
593 result.Add(kAliHLTAnyDataType);
594 for (Int_t i = 0; i < fEntries.GetEntriesFast(); i++)
595 {
596 const AliHLTDomainEntry* entry = static_cast<const AliHLTDomainEntry*>( fEntries[i] );
597 if (entry->Inclusive())
598 {
599 result.Remove(*entry);
600 }
601 else
602 {
603 result.Add(*entry);
604 }
605 }
606 return result;
607}
608
609
610AliHLTTriggerDomain AliHLTTriggerDomain::operator & (const AliHLTTriggerDomain& domain) const
611{
612 // This operator finds the set intersect.
613 // See header file for more details.
614
615 AliHLTTriggerDomain result;
616 Int_t newIndex = 0;
617 AliHLTDomainEntry intersect;
618
619 // To find the set intersect we need to compare each entry in 'domain' to those
620 // of fEntries. For each inclusive entry in 'domain' we need to add to the result
621 // the intersect between it and each entry of fEntries, with the same exclude flag
622 // value as the domain entry from fEntries.
623 // However, in principle, for the exclusion entries in 'domain' we just add them
624 // to the result, since those entries do not form part of the 'domain' trigger
625 // domain set, so they should not form part of the result (remember any data block
626 // must be contained in both trigger domains for a set intersect).
627 // In actual fact we just add the intersect of the exclusion entries in 'domain'
628 // with those of fEntries to the result. This has the same overall effect, but
629 // makes sure that all exclusion entries are always subsets of inclusion entries.
630 for (Int_t i = 0; i < domain.fEntries.GetEntriesFast(); i++)
631 {
632 const AliHLTDomainEntry* checkEntry = static_cast<const AliHLTDomainEntry*>( domain.fEntries[i] );
633 if (checkEntry->Inclusive())
634 {
635 for (Int_t j = 0; j < fEntries.GetEntriesFast(); j++)
636 {
637 AliHLTDomainEntry* currentEntry = static_cast<AliHLTDomainEntry*>( fEntries[j] );
638 if (checkEntry->IntersectWith(*currentEntry, intersect))
639 {
640 // We can remove all entries that were already added to the result that
641 // will become redundent because they are subsets of the new entry.
642 result.MarkForDeletionSubsetsOf(intersect, 0);
643
644 new (result.fEntries[newIndex++]) AliHLTDomainEntry(currentEntry->Exclusive(), intersect);
645 }
646 }
647 }
648 else
649 {
650 for (Int_t j = 0; j < fEntries.GetEntriesFast(); j++)
651 {
652 AliHLTDomainEntry* currentEntry = static_cast<AliHLTDomainEntry*>( fEntries[j] );
653 if (checkEntry->IntersectWith(*currentEntry, intersect))
654 {
655 // We can remove all entries that were already added to the result that
656 // will become redundant because they are subsets of the new entry.
657 result.MarkForDeletionSubsetsOf(intersect, 0);
658
659 new (result.fEntries[newIndex++]) AliHLTDomainEntry(kTRUE, intersect);
660 }
661 }
662 }
663 }
664
665 result.RemoveMarkedEntries();
666 result.Optimise();
667 return result;
668}
669
670
671void AliHLTTriggerDomain::MergeEntries(
672 const bool* removeThisEntry, Int_t entriesCount,
673 const bool* removeDomainEntry, Int_t startOfIntersects,
674 const AliHLTTriggerDomain& domain
675 )
676{
677 // Merges the entries in this trigger domain with the ones in 'domain', while
678 // removing all entries that were marked for removal.
679 // See header file for more information.
680
681 bool anythingRemoved = false;
682
683 // Remember this method is used at the end of the calculation of the binary operators
684 // and that fEntries is expected to be partitioned into 3 regions.
685 // - 0..entriesCount-1 : contains the original (initial) entries of this trigger domain.
686 // - entriesCount..startOfIntersects-1 : is space reserved for the new entries
687 // from the given trigger domain 'domain' being processed.
688 // - startOfIntersects..fEntries.GetEntriesFast()-1 : contains all new domain entry
689 // intersection created and added to fEntries.
690 //
691 // First we need to remove all entries marked for removal from the original entries.
692 for (Int_t i = 0; i < entriesCount; i++)
693 {
694 if (removeThisEntry[i])
695 {
696 fEntries.RemoveAt(i);
697 anythingRemoved = true;
698 }
699 }
700
701 // Now we copy over all the new entries from 'domain' which were not marked for removal
702 // and indicate anythingRemoved = true since there will now be gaps in the clones array
703 // that need to be compressed away later.
704 for (Int_t i = 0; i < domain.fEntries.GetEntriesFast(); i++)
705 {
706 if (removeDomainEntry[i])
707 {
708 anythingRemoved = true;
709 }
710 else
711 {
712 const AliHLTDomainEntry* newEntry = static_cast<const AliHLTDomainEntry*>( domain.fEntries[i] );
713 new (fEntries[entriesCount+i]) AliHLTDomainEntry(*newEntry);
714 }
715 }
716
717 // Finally remove all new intersection entries that were marked for removal by
718 // the MarkForDeletionSubsetsOf method.
719 for (Int_t i = startOfIntersects; i < fEntries.GetEntriesFast(); i++)
720 {
721 const AliHLTDomainEntry* ientry = static_cast<const AliHLTDomainEntry*>( fEntries[i] );
722 if (ientry->TestBit(14))
723 {
724 fEntries.RemoveAt(i);
725 anythingRemoved = true;
726 }
727 }
728 if (anythingRemoved) fEntries.Compress();
729}
730
731
732void AliHLTTriggerDomain::MarkForDeletionSubsetsOf(const AliHLTDomainEntry& entry, Int_t min)
733{
734 // Marks for deletion all the entries in this trigger domain that are subsets
735 // of the given entry.
736 // See header file for more information.
737
738 AliHLTDomainEntry intersect;
739 for (Int_t i = min; i < fEntries.GetEntriesFast(); i++)
740 {
741 AliHLTDomainEntry* ientry = static_cast<AliHLTDomainEntry*>( fEntries[i] );
742 if (ientry->TestBit(14)) continue;
743 if (ientry->SubsetOf(entry))
744 {
745 ientry->SetBit(14, true);
746 }
747 }
748}
749
750
751void AliHLTTriggerDomain::RemoveMarkedEntries()
752{
753 // Removes all entries in this trigger domain which were marked for removal..
754 // See header file for more information.
755
756 bool anythingRemoved = false;
757 for (Int_t i = 0; i < fEntries.GetEntriesFast(); i++)
758 {
759 const AliHLTDomainEntry* ientry = static_cast<const AliHLTDomainEntry*>( fEntries[i] );
760 if (ientry->TestBit(14))
761 {
762 fEntries.RemoveAt(i);
763 anythingRemoved = true;
764 }
765 }
766 if (anythingRemoved) fEntries.Compress();
767}
768
769
770void AliHLTTriggerDomain::Optimise()
771{
772 // Removes redundant trigger domain entries from the trigger domain.
773 // See header file for more information.
774
775 AliHLTDomainEntry intersect;
776
777 // Check that the first entry is not and exclusion which would be redundent.
778 if (fEntries.GetEntriesFast() == 0) return;
779 AliHLTDomainEntry* firstEntry = static_cast<AliHLTDomainEntry*>( fEntries[0] );
780 if (firstEntry->Exclusive()) firstEntry->SetBit(14, true);
781
782 for (Int_t i = 1; i < fEntries.GetEntriesFast(); i++)
783 {
784 AliHLTDomainEntry* ientry = static_cast<AliHLTDomainEntry*>( fEntries[i] );
785
786 // For the i'th entry in fEntries, compare it in reverse order with all other
787 // entries that are before it and look for redundant ones, i.e. that are subsets
788 // of the i'th entry.
789 for (Int_t j = i-1; j >= 0; j--)
790 {
791 AliHLTDomainEntry* jentry = static_cast<AliHLTDomainEntry*>( fEntries[j] );
792 if (jentry->TestBit(14)) continue;
793 // Find entries that intersect
794 if (jentry->SubsetOf(*ientry))
795 {
796 // jentry is a subset of ientry so it is redundant because for all values
797 // ientry will override jentry when calling IncludeInReadout.
798 jentry->SetBit(14, true);
799 }
800 else if (*ientry == *jentry)
801 {
802 // If intersecting entries have opposite exclude flags then search no further,
803 // we know that we will need this entry for correct behaviour of IncludeInReadout.
804 if (ientry->Inclusive() == jentry->Exclusive()) goto processNextEntry;
805
806 if (ientry->SubsetOf(*jentry))
807 {
808 ientry->SetBit(14, true);
809 goto processNextEntry;
810 }
811 }
812 }
813
814 // If we got to this point then we hit the top of the trigger domain rules
815 // (pattern matching) list without hitting any and overlapping entries.
816 // So now we need to check if ientry is an exclusion. If it is, then it is
817 // redundant and we can mark it for removal.
818 if (ientry->Exclusive()) ientry->SetBit(14, true);
819
820 processNextEntry: ;
821 }
822
823 RemoveMarkedEntries();
824}
825