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 | |
29 | ClassImp(AliHLTTriggerDomain) |
30 | |
31 | |
32 | AliHLTTriggerDomain::AliHLTTriggerDomain() : |
33 | TObject(), fEntries(AliHLTDomainEntry::Class(), 10) |
34 | { |
35 | // Default constructor. |
36 | } |
37 | |
38 | |
39 | AliHLTTriggerDomain::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 | |
54 | AliHLTTriggerDomain::~AliHLTTriggerDomain() |
55 | { |
56 | // Default destructor. |
57 | } |
58 | |
59 | |
60 | void 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 | |
120 | void 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 | |
130 | void 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 | |
140 | void 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 | |
150 | void 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 | |
160 | void 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 | |
221 | void 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 | |
230 | void 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 | |
240 | void 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 | |
250 | void 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 | |
260 | bool 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 | |
286 | bool 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 | |
312 | void AliHLTTriggerDomain::Clear(Option_t* option) |
313 | { |
314 | // Clears the trigger domain (Removes all entries). |
315 | |
316 | fEntries.Clear(option); |
317 | } |
318 | |
319 | |
320 | void 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 | |
346 | AliHLTTriggerDomain& 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 | |
363 | AliHLTTriggerDomain& 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 | |
443 | AliHLTTriggerDomain& 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 | |
509 | AliHLTTriggerDomain& 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 | |
582 | AliHLTTriggerDomain 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 | |
610 | AliHLTTriggerDomain 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 | |
671 | void 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 | |
732 | void 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 | |
751 | void 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 | |
770 | void 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 | |