Statistics
| Branch: | Revision:

root / src / eventlog / filteredeventlog.cc @ master

History | View | Annotate | Download (23.4 KB)

1
//=========================================================================
2
//  FILTEREDEVENTLOG.CC - part of
3
//                  OMNeT++/OMNEST
4
//           Discrete System Simulation in C++
5
//
6
//  Author: Levente Meszaros
7
//
8
//=========================================================================
9

    
10
/*--------------------------------------------------------------*
11
  Copyright (C) 2006-2008 OpenSim Ltd.
12

13
  This file is distributed WITHOUT ANY WARRANTY. See the file
14
  `license' for details on this and other legal matters.
15
*--------------------------------------------------------------*/
16

    
17
#include <stdio.h>
18
#include <algorithm>
19
#include "filteredeventlog.h"
20

    
21
USING_NAMESPACE
22

    
23
FilteredEventLog::FilteredEventLog(IEventLog *eventLog)
24
{
25
    this->eventLog = eventLog;
26

    
27
    // collection limits
28
    collectMessageReuses = true;
29
    maximumNumberOfCauses = maximumNumberOfConsequences = 5;
30
    maximumCauseDepth = maximumConsequenceDepth = 15;
31
    maximumCauseCollectionTime = maximumConsequenceCollectionTime = 100;
32

    
33
    // trace filter parameters
34
    tracedEventNumber = -1;
35
    firstEventNumber = -1;
36
    lastEventNumber = -1;
37
    traceCauses = true;
38
    traceConsequences = true;
39
    traceMessageReuses = true;
40
    traceSelfMessages = true;
41

    
42
    // other filter parameters
43
    enableModuleFilter = false;
44
    enableMessageFilter = false;
45
    setModuleExpression("");
46
    setMessageExpression("");
47

    
48
    clearInternalState();
49
}
50

    
51
FilteredEventLog::~FilteredEventLog()
52
{
53
    deleteAllocatedObjects();
54
}
55

    
56
void FilteredEventLog::deleteAllocatedObjects()
57
{
58
    for (EventNumberToFilteredEventMap::iterator it = eventNumberToFilteredEventMap.begin(); it != eventNumberToFilteredEventMap.end(); it++)
59
        delete it->second;
60

    
61
    clearInternalState();
62
}
63

    
64
void FilteredEventLog::clearInternalState(FileReader::FileChangedState change)
65
{
66
    Assert(change != FileReader::UNCHANGED);
67
    approximateNumberOfEvents = -1;
68
    approximateMatchingEventRatio = -1;
69
    lastMatchingEvent = NULL;
70

    
71
    if (change == FileReader::OVERWRITTEN) {
72
        firstMatchingEvent = NULL;
73

    
74
        eventNumberToFilteredEventMap.clear();
75
        eventNumberToFilterMatchesFlagMap.clear();
76
        eventNumberToTraceableEventFlagMap.clear();
77
    }
78
}
79

    
80
void FilteredEventLog::synchronize(FileReader::FileChangedState change)
81
{
82
    if (change != FileReader::UNCHANGED) {
83
        if (change == FileReader::OVERWRITTEN)
84
            deleteAllocatedObjects();
85
        else
86
            clearInternalState(change);
87

    
88
        eventLog->synchronize(change);
89

    
90
        if (change == FileReader::APPENDED)
91
            for (EventNumberToFilteredEventMap::iterator it = eventNumberToFilteredEventMap.begin(); it != eventNumberToFilteredEventMap.end(); it++)
92
                it->second->synchronize();
93
    }
94
}
95

    
96
void FilteredEventLog::setPatternMatchers(std::vector<PatternMatcher> &patternMatchers, std::vector<std::string> &patterns, bool dottedPath)
97
{
98
    for (std::vector<std::string>::iterator it = patterns.begin(); it != patterns.end(); it++) {
99
        PatternMatcher matcher;
100
        matcher.setPattern((*it).c_str(), dottedPath, true, false);
101
        patternMatchers.push_back(matcher);
102
    }
103
}
104

    
105
eventnumber_t FilteredEventLog::getApproximateNumberOfEvents()
106
{
107
    if (approximateNumberOfEvents == -1)
108
    {
109
        if (tracedEventNumber != -1) {
110
            // TODO: this is clearly not good and should return a much better approximation
111
            // TODO: maybe start from traced event number and go forward/backward and return approximation based on that?
112
            if (firstEventNumber != -1 && lastEventNumber != -1)
113
                return lastEventNumber - firstEventNumber;
114
            else
115
                return 1000;
116
        }
117
        else {
118
            // TODO: what if filter is event range limited?
119
            FilteredEvent *firstEvent = getFirstEvent();
120
            FilteredEvent *lastEvent = getLastEvent();
121

    
122
            if (firstEvent == NULL)
123
                approximateNumberOfEvents = 0;
124
            else
125
            {
126
                file_offset_t beginOffset = firstEvent->getBeginOffset();
127
                file_offset_t endOffset = lastEvent->getEndOffset();
128
                long sumMatching = 0;
129
                long sumNotMatching = 0;
130
                long count = 0;
131
                int eventCount = 100;
132

    
133
                // TODO: perhaps it would be better to read in random events
134
                for (int i = 0; i < eventCount; i++)
135
                {
136
                    if (firstEvent) {
137
                        FilteredEvent *previousEvent = firstEvent;
138
                        sumMatching += firstEvent->getEndOffset() - firstEvent->getBeginOffset();
139
                        count++;
140
                        firstEvent = firstEvent->getNextEvent();
141
                        if (firstEvent)
142
                            sumNotMatching += firstEvent->getBeginOffset() - previousEvent->getEndOffset();
143
                    }
144

    
145
                    if (lastEvent) {
146
                        FilteredEvent *previousEvent = lastEvent;
147
                        sumMatching += lastEvent->getEndOffset() - lastEvent->getBeginOffset();
148
                        count++;
149
                        lastEvent = lastEvent->getPreviousEvent();
150
                        if (lastEvent)
151
                            sumNotMatching += previousEvent->getBeginOffset() - lastEvent->getEndOffset();
152
                    }
153
                }
154

    
155
                double averageMatching = (double)sumMatching / count;
156
                double averageNotMatching = (double)sumNotMatching / count;
157
                approximateMatchingEventRatio = averageMatching / (averageMatching + averageNotMatching);
158
                approximateNumberOfEvents = (long)((endOffset - beginOffset) / averageMatching * approximateMatchingEventRatio);
159
            }
160
        }
161
    }
162

    
163
    return approximateNumberOfEvents;
164
}
165

    
166
double FilteredEventLog::getApproximatePercentageForEventNumber(eventnumber_t eventNumber)
167
{
168
    if (tracedEventNumber != -1)
169
        // TODO: this is clearly not good and should return a much better approximation
170
        return IEventLog::getApproximatePercentageForEventNumber(eventNumber);
171
    else
172
        // TODO: what if filter is event range limited
173
        return IEventLog::getApproximatePercentageForEventNumber(eventNumber);
174
}
175

    
176
FilteredEvent *FilteredEventLog::getApproximateEventAt(double percentage)
177
{
178
    if (isEmpty())
179
        return NULL;
180
    else {
181
        double firstEventPercentage = eventLog->getApproximatePercentageForEventNumber(getFirstEvent()->getEventNumber());
182
        double lastEventPercentage = eventLog->getApproximatePercentageForEventNumber(getLastEvent()->getEventNumber());
183
        percentage = firstEventPercentage + percentage * (lastEventPercentage - firstEventPercentage);
184
        IEvent *event = eventLog->getApproximateEventAt(percentage);
185

    
186
        FilteredEvent *filteredEvent = getMatchingEventInDirection(event, true);
187
        if (filteredEvent)
188
            return filteredEvent;
189

    
190
        filteredEvent = getMatchingEventInDirection(event, false);
191
        if (filteredEvent)
192
            return filteredEvent;
193

    
194
        Assert(false);
195
    }
196
}
197

    
198
FilteredEvent *FilteredEventLog::getNeighbourEvent(IEvent *event, eventnumber_t distance)
199
{
200
    return (FilteredEvent *)IEventLog::getNeighbourEvent(event, distance);
201
}
202

    
203
bool FilteredEventLog::matchesFilter(IEvent *event)
204
{
205
    Assert(event);
206
    EventNumberToBooleanMap::iterator it = eventNumberToFilterMatchesFlagMap.find(event->getEventNumber());
207

    
208
    // if cached, return it
209
    if (it != eventNumberToFilterMatchesFlagMap.end())
210
        return it->second;
211

    
212
    //printf("*** Matching filter to event: %ld\n", event->getEventNumber());
213

    
214
    bool matches = matchesEvent(event) && matchesDependency(event);
215
    eventNumberToFilterMatchesFlagMap[event->getEventNumber()] = matches;
216
    return matches;
217
}
218

    
219
bool FilteredEventLog::matchesEvent(IEvent *event)
220
{
221
    // event outside of considered range
222
    if ((firstEventNumber != -1 && event->getEventNumber() < firstEventNumber) ||
223
        (lastEventNumber != -1 && event->getEventNumber() > lastEventNumber))
224
        return false;
225

    
226
    // event's module
227
    if (enableModuleFilter) {
228
        ModuleCreatedEntry *eventModuleCreatedEntry = event->getModuleCreatedEntry();
229
        ModuleCreatedEntry *moduleCreatedEntry = eventModuleCreatedEntry;
230
        // match parent chain of event's module (to handle compound modules too)
231
        while (moduleCreatedEntry) {
232
            if (matchesModuleCreatedEntry(moduleCreatedEntry)) {
233
                if (moduleCreatedEntry == eventModuleCreatedEntry)
234
                    goto MATCHES;
235
                else {
236
                    // check if the event has a cause or consequence referring
237
                    // outside the matching compound module
238
                    IMessageDependencyList *causes = event->getCauses();
239
                    for (IMessageDependencyList::iterator it = causes->begin(); it != causes->end(); it++) {
240
                        IEvent *causeEvent = (*it)->getCauseEvent();
241
                        if (causeEvent && !isAncestorModuleCreatedEntry(moduleCreatedEntry, causeEvent->getModuleCreatedEntry()))
242
                            goto MATCHES;
243
                    }
244

    
245
                    IMessageDependencyList *consequences = event->getConsequences();
246
                    for (IMessageDependencyList::iterator it = consequences->begin(); it != consequences->end(); it++) {
247
                        IEvent *consequenceEvent = (*it)->getConsequenceEvent();
248
                        if (consequenceEvent && !isAncestorModuleCreatedEntry(moduleCreatedEntry, consequenceEvent->getModuleCreatedEntry()))
249
                            goto MATCHES;
250
                    }
251
                }
252
            }
253

    
254
            moduleCreatedEntry = getModuleCreatedEntry(moduleCreatedEntry->parentModuleId);
255
        }
256

    
257
        // no match
258
        return false;
259
        // match found
260
        MATCHES:;
261
    }
262

    
263
    // event's message
264
    if (enableMessageFilter) {
265
        BeginSendEntry *beginSendEntry = event->getCauseBeginSendEntry();
266
        bool matches = beginSendEntry ? matchesBeginSendEntry(beginSendEntry) : false;
267

    
268
        for (int i = 0; i < event->getNumEventLogEntries(); i++) {
269
            beginSendEntry = dynamic_cast<BeginSendEntry *>(event->getEventLogEntry(i));
270

    
271
            if (beginSendEntry && matchesBeginSendEntry(beginSendEntry)) {
272
                matches = true;
273
                break;
274
            }
275
        }
276

    
277
        if (!matches)
278
            return false;
279
    }
280

    
281
    return true;
282
}
283

    
284
bool FilteredEventLog::matchesDependency(IEvent *event)
285
{
286
    // if there's no traced event
287
    if (tracedEventNumber == -1)
288
        return true;
289

    
290
    // if this is the traced event
291
    if (event->getEventNumber() == tracedEventNumber)
292
        return true;
293

    
294
    // event is cause of traced event
295
    if (tracedEventNumber > event->getEventNumber() && traceCauses)
296
        return isCauseOfTracedEvent(event);
297

    
298
    // event is consequence of traced event
299
    if (tracedEventNumber < event->getEventNumber() && traceConsequences)
300
        return isConsequenceOfTracedEvent(event);
301

    
302
    return false;
303
}
304

    
305
bool FilteredEventLog::matchesModuleCreatedEntry(ModuleCreatedEntry *moduleCreatedEntry)
306
{
307
    return
308
        matchesExpression(moduleExpression, moduleCreatedEntry) ||
309
        matchesPatterns(moduleNames, moduleCreatedEntry->fullName) ||
310
        matchesPatterns(moduleClassNames, moduleCreatedEntry->moduleClassName) ||
311
        matchesPatterns(moduleNEDTypeNames, moduleCreatedEntry->nedTypeName) ||
312
        matchesList(moduleIds, moduleCreatedEntry->moduleId);
313
}
314

    
315
bool FilteredEventLog::matchesBeginSendEntry(BeginSendEntry *beginSendEntry)
316
{
317
    return
318
        matchesExpression(messageExpression, beginSendEntry) ||
319
        matchesPatterns(messageNames, beginSendEntry->messageFullName) ||
320
        matchesPatterns(messageClassNames, beginSendEntry->messageClassName) ||
321
        matchesList(messageIds, beginSendEntry->messageId) ||
322
        matchesList(messageTreeIds, beginSendEntry->messageTreeId) ||
323
        matchesList(messageEncapsulationIds, beginSendEntry->messageEncapsulationId) ||
324
        matchesList(messageEncapsulationTreeIds, beginSendEntry->messageEncapsulationTreeId);
325
}
326

    
327
bool FilteredEventLog::matchesExpression(MatchExpression &matchExpression, EventLogEntry *eventLogEntry)
328
{
329
    return matchExpression.matches(eventLogEntry);
330
}
331

    
332
bool FilteredEventLog::matchesPatterns(std::vector<PatternMatcher> &patterns, const char *str)
333
{
334
    if (patterns.empty())
335
        return false;
336

    
337
    for (std::vector<PatternMatcher>::iterator it = patterns.begin(); it != patterns.end(); it++)
338
        if ((*it).matches(str))
339
            return true;
340

    
341
    return false;
342
}
343

    
344
template <typename T> bool FilteredEventLog::matchesList(std::vector<T> &elements, T element)
345
{
346
    if (elements.empty())
347
        return false;
348
    else
349
        return std::find(elements.begin(), elements.end(), element) != elements.end();
350
}
351

    
352
bool FilteredEventLog::isEmpty()
353
{
354
    if (tracedEventNumber != -1) {
355
        IEvent *event = eventLog->getEventForEventNumber(tracedEventNumber);
356

    
357
        if (event && matchesFilter(event))
358
            return false;
359
    }
360

    
361
    return IEventLog::isEmpty();
362
}
363

    
364
FilteredEvent *FilteredEventLog::getFirstEvent()
365
{
366
    if (!firstMatchingEvent && !eventLog->isEmpty())
367
    {
368
        eventnumber_t startEventNumber = firstEventNumber == -1 ? eventLog->getFirstEvent()->getEventNumber() : std::max(eventLog->getFirstEvent()->getEventNumber(), firstEventNumber);
369
        firstMatchingEvent = getMatchingEventInDirection(startEventNumber, true);
370
    }
371

    
372
    return firstMatchingEvent;
373
}
374

    
375
FilteredEvent *FilteredEventLog::getLastEvent()
376
{
377
    if (!lastMatchingEvent && !eventLog->isEmpty())
378
    {
379
        eventnumber_t startEventNumber = lastEventNumber == -1 ? eventLog->getLastEvent()->getEventNumber() : std::min(eventLog->getLastEvent()->getEventNumber(), lastEventNumber);
380
        lastMatchingEvent = getMatchingEventInDirection(startEventNumber, false);
381
    }
382

    
383
    return lastMatchingEvent;
384
}
385

    
386
FilteredEvent *FilteredEventLog::getEventForEventNumber(eventnumber_t eventNumber, MatchKind matchKind)
387
{
388
    Assert(eventNumber >= 0);
389

    
390
    EventNumberToFilteredEventMap::iterator it = eventNumberToFilteredEventMap.find(eventNumber);
391

    
392
    if (it != eventNumberToFilteredEventMap.end())
393
        return it->second;
394

    
395
    IEvent *event = eventLog->getEventForEventNumber(eventNumber, matchKind);
396

    
397
    if (event) {
398
        switch (matchKind) {
399
            case EXACT:
400
                if (matchesFilter(event))
401
                    return cacheFilteredEvent(event->getEventNumber());
402
                break;
403
            case FIRST_OR_PREVIOUS:
404
                if (event->getEventNumber() == eventNumber && matchesFilter(event))
405
                    return cacheFilteredEvent(event->getEventNumber());
406
                else
407
                    return getMatchingEventInDirection(event, false);
408
            case FIRST_OR_NEXT:
409
                return getMatchingEventInDirection(event, true);
410
            case LAST_OR_PREVIOUS:
411
                return getMatchingEventInDirection(event, false);
412
            case LAST_OR_NEXT:
413
                if (event->getEventNumber() == eventNumber && matchesFilter(event))
414
                    return cacheFilteredEvent(event->getEventNumber());
415
                else
416
                    return getMatchingEventInDirection(event, true);
417
        }
418
    }
419

    
420
    return NULL;
421
}
422

    
423
FilteredEvent *FilteredEventLog::getEventForSimulationTime(simtime_t simulationTime, MatchKind matchKind)
424
{
425
    IEvent *event = eventLog->getEventForSimulationTime(simulationTime, matchKind);
426

    
427
    if (event) {
428
        switch (matchKind) {
429
            case EXACT:
430
                if (matchesFilter(event))
431
                    return cacheFilteredEvent(event->getEventNumber());
432
                break;
433
            case FIRST_OR_PREVIOUS:
434
                if (event->getSimulationTime() == simulationTime) {
435
                    IEvent *lastEvent = eventLog->getEventForSimulationTime(simulationTime, LAST_OR_NEXT);
436
                    FilteredEvent *matchingEvent = getMatchingEventInDirection(event, true, lastEvent->getEventNumber());
437

    
438
                    if (matchingEvent)
439
                        return matchingEvent;
440
                }
441

    
442
                return getMatchingEventInDirection(event, false);
443
            case FIRST_OR_NEXT:
444
                return getMatchingEventInDirection(event, true);
445
            case LAST_OR_PREVIOUS:
446
                return getMatchingEventInDirection(event, false);
447
            case LAST_OR_NEXT:
448
                if (event->getSimulationTime() == simulationTime) {
449
                    IEvent *firstEvent = eventLog->getEventForSimulationTime(simulationTime, FIRST_OR_PREVIOUS);
450
                    FilteredEvent *matchingEvent = getMatchingEventInDirection(event, false, firstEvent->getEventNumber());
451

    
452
                    if (matchingEvent)
453
                        return matchingEvent;
454
                }
455

    
456
                return getMatchingEventInDirection(event, true);
457
        }
458
    }
459

    
460
    return NULL;
461
}
462

    
463
EventLogEntry *FilteredEventLog::findEventLogEntry(EventLogEntry *start, const char *search, bool forward, bool caseSensitive)
464
{
465
    EventLogEntry *eventLogEntry = start;
466

    
467
    do {
468
        eventLogEntry = eventLog->findEventLogEntry(eventLogEntry, search, forward, caseSensitive);
469
    }
470
    while (!matchesFilter(eventLogEntry->getEvent()));
471

    
472
    return eventLogEntry;
473
}
474

    
475
FilteredEvent *FilteredEventLog::getMatchingEventInDirection(eventnumber_t eventNumber, bool forward, eventnumber_t stopEventNumber)
476
{
477
    Assert(eventNumber >= 0);
478
    IEvent *event = eventLog->getEventForEventNumber(eventNumber);
479

    
480
    return getMatchingEventInDirection(event, forward, stopEventNumber);
481
}
482

    
483
FilteredEvent *FilteredEventLog::getMatchingEventInDirection(IEvent *event, bool forward, eventnumber_t stopEventNumber)
484
{
485
    Assert(event);
486

    
487
    // optimization
488
    if (forward) {
489
        if (firstMatchingEvent && event->getEventNumber() < firstMatchingEvent->getEventNumber()) {
490
            if (stopEventNumber != -1 && stopEventNumber < firstMatchingEvent->getEventNumber())
491
                return NULL;
492
            else
493
                return firstMatchingEvent;
494
        }
495

    
496
        if (firstEventNumber != -1 && event->getEventNumber() < firstEventNumber)
497
            event = eventLog->getEventForEventNumber(firstEventNumber, LAST_OR_NEXT);
498
    }
499
    else {
500
        if (lastMatchingEvent && lastMatchingEvent->getEventNumber() < event->getEventNumber()) {
501
            if (stopEventNumber != -1 && lastMatchingEvent->getEventNumber() < stopEventNumber)
502
                return NULL;
503
            else
504
                return lastMatchingEvent;
505
        }
506
        if (lastEventNumber != -1 && lastEventNumber < event->getEventNumber())
507
            event = eventLog->getEventForEventNumber(lastEventNumber, FIRST_OR_PREVIOUS);
508
    }
509

    
510
    Assert(event);
511

    
512
    // TODO: LONG RUNNING OPERATION
513
    // if none of firstEventNumber, lastEventNumber, stopEventNumber is set this might take a while
514
    while (event)
515
    {
516
        eventLog->progress();
517
        int eventNumber = event->getEventNumber();
518

    
519
        if (matchesFilter(event))
520
            return cacheFilteredEvent(eventNumber);
521

    
522
        if (forward)
523
        {
524
            eventNumber++;
525
            event = event->getNextEvent();
526

    
527
            if (lastEventNumber != -1 && eventNumber > lastEventNumber)
528
                return NULL;
529

    
530
            if (stopEventNumber != -1 && eventNumber > stopEventNumber)
531
                return NULL;
532
        }
533
        else {
534
            eventNumber--;
535
            event = event->getPreviousEvent();
536

    
537
            if (firstEventNumber != -1 && eventNumber < firstEventNumber)
538
                return NULL;
539

    
540
            if (stopEventNumber != -1 && eventNumber < stopEventNumber)
541
                return NULL;
542
        }
543
    }
544

    
545
    return NULL;
546
}
547

    
548
// TODO: LONG RUNNING OPERATION
549
// this does a recursive depth search
550
bool FilteredEventLog::isCauseOfTracedEvent(IEvent *cause)
551
{
552
    eventLog->progress();
553
    EventNumberToBooleanMap::iterator it = eventNumberToTraceableEventFlagMap.find(cause->getEventNumber());
554

    
555
    // check cache
556
    if (it != eventNumberToTraceableEventFlagMap.end())
557
        return it->second;
558

    
559
    //printf("Checking if %ld is cause of %ld\n", cause->getEventNumber(), tracedEventNumber);
560

    
561
    // returns true if "consequence" can be reached from "cause", using
562
    // the consequences chain. We use depth-first search.
563
    bool result = false;
564
    IMessageDependencyList *consequences = cause->getConsequences();
565

    
566
    for (IMessageDependencyList::iterator it = consequences->begin(); it != consequences->end(); it++)
567
    {
568
        IMessageDependency *messageDependency = *it;
569
        IEvent *consequenceEvent = messageDependency->getConsequenceEvent();
570

    
571
        if (consequenceEvent &&
572
            (traceSelfMessages || !consequenceEvent->isSelfMessageProcessingEvent()) &&
573
            (traceMessageReuses || !messageDependency->getIsReuse()))
574
        {
575
            // if we reached the consequence event, we're done
576
            if (tracedEventNumber == consequenceEvent->getEventNumber())
577
                result = true;
578

    
579
            // try depth-first search if we haven't passed the consequence event yet
580
            if (tracedEventNumber > consequenceEvent->getEventNumber() &&
581
                isCauseOfTracedEvent(consequenceEvent))
582
                result = true;
583
        }
584
    }
585

    
586
    eventNumberToTraceableEventFlagMap[cause->getEventNumber()] = result;
587

    
588
    return result;
589
}
590

    
591
// TODO: LONG RUNNING OPERATION
592
// this does a recursive depth search
593
bool FilteredEventLog::isConsequenceOfTracedEvent(IEvent *consequence)
594
{
595
    eventLog->progress();
596

    
597
    if (!traceSelfMessages && consequence->isSelfMessageProcessingEvent())
598
        return false;
599

    
600
    EventNumberToBooleanMap::iterator it = eventNumberToTraceableEventFlagMap.find(consequence->getEventNumber());
601

    
602
    // check cache
603
    if (it != eventNumberToTraceableEventFlagMap.end())
604
        return it->second;
605

    
606
    //printf("Checking if %ld is consequence of %ld\n", consequence->getEventNumber(), tracedEventNumber);
607

    
608
    // like consequenceEvent(), but searching from the opposite direction
609
    bool result = false;
610
    IMessageDependencyList *causes = consequence->getCauses();
611

    
612
    for (IMessageDependencyList::iterator it = causes->begin(); it != causes->end(); it++)
613
    {
614
        IMessageDependency *messageDependency = *it;
615
        IEvent *causeEvent = messageDependency->getCauseEvent();
616

    
617
        if (causeEvent && (traceMessageReuses || !messageDependency->getIsReuse()))
618
        {
619
            // if we reached the cause event, we're done
620
            if (tracedEventNumber == causeEvent->getEventNumber())
621
                result = true;
622

    
623
            // try depth-first search if we haven't passed the cause event yet
624
            if (tracedEventNumber < causeEvent->getEventNumber() &&
625
                isConsequenceOfTracedEvent(causeEvent))
626
                result = true;
627
        }
628
    }
629

    
630
    eventNumberToTraceableEventFlagMap[consequence->getEventNumber()] = result;
631

    
632
    return result;
633
}
634

    
635
FilteredEvent *FilteredEventLog::cacheFilteredEvent(eventnumber_t eventNumber)
636
{
637
    EventNumberToFilteredEventMap::iterator it = eventNumberToFilteredEventMap.find(eventNumber);
638

    
639
    if (it != eventNumberToFilteredEventMap.end())
640
        return it->second;
641
    else {
642
        FilteredEvent *filteredEvent = new FilteredEvent(this, eventNumber);
643
        eventNumberToFilteredEventMap[eventNumber] = filteredEvent;
644
        return filteredEvent;
645
    }
646
}
647

    
648
bool FilteredEventLog::isAncestorModuleCreatedEntry(ModuleCreatedEntry *ancestor, ModuleCreatedEntry *descendant)
649
{
650
    while (descendant) {
651
        if (descendant == ancestor)
652
            return true;
653
        else
654
            descendant = getModuleCreatedEntry(descendant->parentModuleId);
655
    }
656

    
657
    return false;
658
}