Statistics
| Branch: | Revision:

root / src / eventlog / filteredevent.cc @ 842775ab

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