Statistics
| Branch: | Revision:

root / src / eventlog / filteredevent.cc @ master

History | View | Annotate | Download (11.8 KB)

1 01873262 Georg Kunz
//=========================================================================
2
//  FILTEREDEVENT.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 "event.h"
19
#include "filteredevent.h"
20
#include "filteredeventlog.h"
21
22
USING_NAMESPACE
23
24
FilteredEvent::FilteredEvent(FilteredEventLog *filteredEventLog, eventnumber_t eventNumber)
25
{
26
    this->eventNumber = eventNumber;
27
    this->filteredEventLog = filteredEventLog;
28
29
    causeEventNumber = -1;
30
    cause = NULL;
31
    causes = NULL;
32
    consequences = NULL;
33
}
34
35
FilteredEvent::~FilteredEvent()
36
{
37
    delete cause;
38
39
    if (causes)
40
    {
41
        for (IMessageDependencyList::iterator it = causes->begin(); it != causes->end(); it++)
42
            delete *it;
43
        delete causes;
44
    }
45
46
    if (consequences)
47
    {
48
        for (IMessageDependencyList::iterator it = consequences->begin(); it != consequences->end(); it++)
49
            delete *it;
50
        delete consequences;
51
    }
52
}
53
54
void FilteredEvent::synchronize()
55
{
56
    if (consequences)
57
    {
58
        for (IMessageDependencyList::iterator it = consequences->begin(); it != consequences->end(); it++)
59
            delete *it;
60
        delete consequences;
61
62
        consequences = NULL;
63
    }
64
}
65
66
IEventLog *FilteredEvent::getEventLog()
67
{
68
    return filteredEventLog;
69
}
70
71
IEvent *FilteredEvent::getEvent()
72
{
73
    return filteredEventLog->getEventLog()->getEventForEventNumber(eventNumber);
74
}
75
76
FilteredEvent *FilteredEvent::getPreviousEvent()
77
{
78
    if (!previousEvent && filteredEventLog->getFirstEvent() != this)
79
    {
80
        previousEvent = filteredEventLog->getMatchingEventInDirection(getEvent()->getPreviousEvent(), false);
81
82
        if (previousEvent)
83
            IEvent::linkEvents(previousEvent, this);
84
    }
85
86
    return (FilteredEvent *)previousEvent;
87
}
88
89
FilteredEvent *FilteredEvent::getNextEvent()
90
{
91
    if (!nextEvent && filteredEventLog->getLastEvent() != this)
92
    {
93
        nextEvent = filteredEventLog->getMatchingEventInDirection(getEvent()->getNextEvent(), true);
94
95
        if (nextEvent)
96
            Event::linkEvents(this, nextEvent);
97
    }
98
99
    return (FilteredEvent *)nextEvent;
100
}
101
102
FilteredEvent *FilteredEvent::getCauseEvent()
103
{
104
    if (causeEventNumber == -1)
105
    {
106
        IEvent *causeEvent = getEvent()->getCauseEvent();
107
108
        // TODO: LONG RUNNING OPERATION
109
        // walk backwards on the cause chain until we find an event matched by the filter
110
        // this might read all events backward if none of the causes matches the filter
111
        while (causeEvent)
112
        {
113
            filteredEventLog->progress();
114
115
            if (causeEvent->getEventNumber() < filteredEventLog->getFirstEventNumber())
116
                return NULL;
117
118
            if (filteredEventLog->matchesFilter(causeEvent))
119
                return filteredEventLog->getEventForEventNumber(causeEvent->getEventNumber());
120
121
            causeEvent = causeEvent->getCauseEvent();
122
        }
123
    }
124
125
    return filteredEventLog->getEventForEventNumber(causeEventNumber);
126
}
127
128
BeginSendEntry *FilteredEvent::getCauseBeginSendEntry()
129
{
130
    IMessageDependency *cause = getCause();
131
    if (cause)
132
        return cause->getBeginSendEntry();
133
    else
134
        return NULL;
135
}
136
137
IMessageDependency *FilteredEvent::getCause()
138
{
139
    if (cause == NULL)
140
    {
141
        IEvent *causeEvent = getEvent();
142
        IMessageDependency *causeMessageDependency = causeEvent->getCause();
143
144
        if (causeMessageDependency) {
145
            IMessageDependency *messageDependency;
146
147
            // TODO: LONG RUNNING OPERATION
148
            // this might read all events backward if none of the causes matches the filter
149
            while (causeEvent && (messageDependency = causeEvent->getCause()))
150
            {
151
                filteredEventLog->progress();
152
153
                if (causeEvent->getEventNumber() < filteredEventLog->getFirstEventNumber())
154
                    return NULL;
155
156
                if (filteredEventLog->matchesFilter(messageDependency->getCauseEvent()))
157
                {
158
                    if (messageDependency == causeMessageDependency)
159
                        cause = messageDependency->duplicate(filteredEventLog);
160
                    else
161
                        cause = new FilteredMessageDependency(filteredEventLog, false,
162
                                    messageDependency->duplicate(filteredEventLog->getEventLog()),
163
                                    causeMessageDependency->duplicate(filteredEventLog->getEventLog()));
164
                    break;
165
                }
166
167
                causeEvent = causeEvent->getCauseEvent();
168
            }
169
        }
170
    }
171
172
    return cause;
173
}
174
175
IMessageDependencyList *FilteredEvent::getCauses()
176
{
177
    if (causes == NULL)
178
    {
179
        // returns a list of dependencies, where the consequence is this event,
180
        // and the other end is no further away than getMaximumCauseDepth() and
181
        // no events in between match the filter
182
        long begin = clock();
183
        causes = new IMessageDependencyList();
184
        std::list<BreadthSearchItem> todoList;
185
        todoList.push_back(BreadthSearchItem(getEvent(), NULL, false, 0));
186
187
        // TODO: LONG RUNNING OPERATION
188
        // this is recursive and might take some time
189
        while (!todoList.empty()) {
190
            filteredEventLog->progress();
191
            if (clock() - begin >= filteredEventLog->getMaximumCauseCollectionTime() * CLOCKS_PER_SEC / 1000)
192
                break;
193
194
            BreadthSearchItem searchItem = todoList.front();
195
            todoList.pop_front();
196
197
            // unpack
198
            IEvent *currentEvent = searchItem.event;
199
            IMessageDependency *endMessageDependency = searchItem.firstSeenMessageDependency;
200
            bool currentIsReuse = searchItem.effectiveIsReuse;
201
            int level = searchItem.level;
202
203
            IMessageDependencyList *eventCauses = currentEvent->getCauses();
204
            for (IMessageDependencyList::iterator it = eventCauses->begin(); it != eventCauses->end(); it++)
205
            {
206
                IMessageDependency *messageDependency = *it;
207
                IEvent *causeEvent = messageDependency->getCauseEvent();
208
209
                if (causeEvent && (filteredEventLog->getCollectMessageReuses() || !messageDependency->getIsReuse())) {
210
                    //printf("*** Checking at level %d for cause event number %ld\n", level, causeEvent->getEventNumber());
211
                    bool effectiveIsReuse = currentIsReuse || messageDependency->getIsReuse();
212
                    if (filteredEventLog->matchesFilter(causeEvent) &&
213
                        (level == 0 || IMessageDependency::corresponds(messageDependency, endMessageDependency)))
214
                    {
215
                        if (level == 0)
216
                            causes->push_back(messageDependency->duplicate(filteredEventLog));
217
                        else
218
                            pushNewFilteredMessageDependency(causes, effectiveIsReuse, messageDependency, endMessageDependency);
219
220
                        if (countFilteredMessageDependencies(causes) == filteredEventLog->getMaximumNumberOfCauses())
221
                            return causes;
222
                    }
223
                    else if (level < filteredEventLog->getMaximumCauseDepth())
224
                        todoList.push_back(BreadthSearchItem(causeEvent,
225
                            level == 0 ? messageDependency : endMessageDependency,
226
                            effectiveIsReuse, level + 1));
227
                }
228
            }
229
        }
230
    }
231
232
    return causes;
233
}
234
235
IMessageDependencyList *FilteredEvent::getConsequences()
236
{
237
    if (consequences == NULL)
238
    {
239
        // similar to getCause
240
        long begin = clock();
241
        consequences = new IMessageDependencyList();
242
        std::list<BreadthSearchItem> todoList;
243
        todoList.push_back(BreadthSearchItem(getEvent(), NULL, false, 0));
244
245
        // TODO: LONG RUNNING OPERATION
246
        // this is recursive and might take some time
247
        while (!todoList.empty()) {
248
            filteredEventLog->progress();
249
            if (clock() - begin >= filteredEventLog->getMaximumConsequenceCollectionTime() * CLOCKS_PER_SEC / 1000)
250
                break;
251
252
            BreadthSearchItem searchItem = todoList.front();
253
            todoList.pop_front();
254
255
            // unpack
256
            IEvent *currentEvent = searchItem.event;
257
            IMessageDependency *beginMessageDependency = searchItem.firstSeenMessageDependency;
258
            bool currentIsReuse = searchItem.effectiveIsReuse;
259
            int level = searchItem.level;
260
261
            IMessageDependencyList *eventConsequences = currentEvent->getConsequences();
262
            for (IMessageDependencyList::iterator it = eventConsequences->begin(); it != eventConsequences->end(); it++)
263
            {
264
                IMessageDependency *messageDependency = *it;
265
                IEvent *consequenceEvent = messageDependency->getConsequenceEvent();
266
267
                if (consequenceEvent && (filteredEventLog->getCollectMessageReuses() || !messageDependency->getIsReuse())) {
268
                    //printf("*** Checking at level %d for consequence event number %ld\n", level, consequenceEvent->getEventNumber());
269
                    bool effectiveIsReuse = currentIsReuse | messageDependency->getIsReuse();
270
                    if (filteredEventLog->matchesFilter(consequenceEvent) &&
271
                        (level == 0 || IMessageDependency::corresponds(beginMessageDependency, messageDependency)))
272
                    {
273
                        if (level == 0)
274
                            consequences->push_back(messageDependency->duplicate(filteredEventLog));
275
                        else
276
                            pushNewFilteredMessageDependency(consequences, effectiveIsReuse, beginMessageDependency, messageDependency);
277
278
                        if (countFilteredMessageDependencies(consequences) == filteredEventLog->getMaximumNumberOfConsequences())
279
                            return consequences;
280
                    }
281
                    else if (level < filteredEventLog->getMaximumConsequenceDepth())
282
                        todoList.push_back(BreadthSearchItem(consequenceEvent,
283
                            level == 0 ? messageDependency : beginMessageDependency,
284
                            effectiveIsReuse, level + 1));
285
                }
286
            }
287
        }
288
    }
289
290
    return consequences;
291
}
292
293
int FilteredEvent::countFilteredMessageDependencies(IMessageDependencyList *messageDependencies)
294
{
295
    int count = 0;
296
    for (IMessageDependencyList::iterator it = messageDependencies->begin(); it != messageDependencies->end(); it++)
297
        if (dynamic_cast<FilteredMessageDependency *>(*it))
298
            count++;
299
300
    return count;
301
}
302
303
void FilteredEvent::pushNewFilteredMessageDependency(IMessageDependencyList *messageDependencies, bool isReuse, IMessageDependency *beginMessageDependency, IMessageDependency *endMessageDependency)
304
{
305
    FilteredMessageDependency *newMessageDependency = new FilteredMessageDependency(filteredEventLog, isReuse,
306
            beginMessageDependency->duplicate(filteredEventLog->getEventLog()),
307
            endMessageDependency->duplicate(filteredEventLog->getEventLog()));
308
309
    for (IMessageDependencyList::iterator it = messageDependencies->begin(); it != messageDependencies->end(); it++) {
310
        if ((*it)->equals(newMessageDependency)) {
311
            delete newMessageDependency;
312
            return;
313
        }
314
    }
315
316
    messageDependencies->push_back(newMessageDependency);
317
}
318 bcffd494 Simon Tenbusch
long FilteredEvent::getEarliestProcessingTime() {
319
    return _earliestProcessingTime;
320
}
321
long FilteredEvent::getEarliestStartTime() {
322
    return ((_earliestProcessingTime == 0) ? 0 : _earliestProcessingTime - getComplexity());
323
}