Statistics
| Branch: | Revision:

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

History | View | Annotate | Download (12.9 KB)

1
//=========================================================================
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
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
FilteredEvent::FilteredEvent(FilteredEventLog *filteredEventLog, eventnumber_t eventNumber)
35
{
36
    this->eventNumber = eventNumber;
37
    this->filteredEventLog = filteredEventLog;
38
    clearInternalState();
39
}
40

    
41
void FilteredEvent::clearInternalState()
42
{
43
    causeEventNumber = -1;
44
    cause = NULL;
45
    causes = NULL;
46
    consequences = NULL;
47
}
48

    
49
FilteredEvent::~FilteredEvent()
50
{
51
    deleteAllocatedObjects();
52
}
53

    
54
void FilteredEvent::deleteConsequences()
55
{
56
    if (consequences) {
57
        for (IMessageDependencyList::iterator it = consequences->begin(); it != consequences->end(); it++)
58
            delete *it;
59
        delete consequences;
60
        consequences = NULL;
61
    }
62
}
63

    
64
void FilteredEvent::deleteAllocatedObjects()
65
{
66
    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
            delete *it;
73
        delete causes;
74
        causes = NULL;
75
    }
76
    deleteConsequences();
77
}
78

    
79
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
    }
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
    if (!previousEvent && filteredEventLog->getFirstEvent() != this) {
109
        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
    if (!nextEvent && filteredEventLog->getLastEvent() != this) {
121
        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
    if (causeEventNumber == -1) {
133
        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
        while (causeEvent) {
139
            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
    if (cause) {
158
        MessageEntry *messageEntry = cause->getMessageEntry();
159
        if (dynamic_cast<BeginSendEntry *>(messageEntry))
160
            return (BeginSendEntry *)messageEntry;
161
        else
162
            return NULL;
163
    }
164
    else
165
        return NULL;
166
}
167

    
168
IMessageDependency *FilteredEvent::getCause()
169
{
170
    if (cause == NULL) {
171
        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
            while (causeEvent && (messageDependency = causeEvent->getCause())) {
180
                filteredEventLog->progress();
181

    
182
                if (causeEvent->getEventNumber() < filteredEventLog->getFirstEventNumber())
183
                    return NULL;
184

    
185
                if (filteredEventLog->matchesFilter(messageDependency->getCauseEvent())) {
186
                    if (messageDependency == causeMessageDependency)
187
                        cause = messageDependency->duplicate(filteredEventLog);
188
                    else
189
                        cause = new FilteredMessageDependency(filteredEventLog, FilteredMessageDependency::SENDS,
190
                                    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
    if (causes == NULL) {
206
        // 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
        todoList.push_back(BreadthSearchItem(getEvent(), NULL, FilteredMessageDependency::UNDEFINED, 0));
213

    
214
        // TODO: LONG RUNNING OPERATION
215
        // this is recursive and might take some time
216
        while (!todoList.empty()) {
217
            filteredEventLog->progress();
218
            if ((long)clock() - begin >= filteredEventLog->getMaximumCauseCollectionTime() * CLOCKS_PER_SEC / 1000)
219
                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
            FilteredMessageDependency::Kind currentKind = searchItem.effectiveKind;
228
            int level = searchItem.level;
229

    
230
            IMessageDependencyList *eventCauses = currentEvent->getCauses();
231
            for (IMessageDependencyList::iterator it = eventCauses->begin(); it != eventCauses->end(); it++) {
232
                IMessageDependency *messageDependency = *it;
233
                IEvent *causeEvent = messageDependency->getCauseEvent();
234

    
235
                if (causeEvent && (filteredEventLog->getCollectMessageReuses() || !dynamic_cast<MessageReuseDependency *>(messageDependency))) {
236
                    //printf("*** Checking at level %d for cause event number %ld\n", level, causeEvent->getEventNumber());
237
                    FilteredMessageDependency::Kind effectiveKind = (FilteredMessageDependency::Kind)((int)currentKind | (int)getMessageDependencyKind(messageDependency));
238
                    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
                            pushNewFilteredMessageDependency(causes, effectiveKind, messageDependency, endMessageDependency);
245

    
246
                        if (countFilteredMessageDependencies(causes) == filteredEventLog->getMaximumNumberOfCauses())
247
                            return causes;
248
                    }
249
                    else if (level < filteredEventLog->getMaximumCauseDepth())
250
                        todoList.push_back(BreadthSearchItem(causeEvent, level == 0 ? messageDependency : endMessageDependency, effectiveKind, level + 1));
251
                }
252
            }
253
        }
254
    }
255

    
256
    return causes;
257
}
258

    
259
IMessageDependencyList *FilteredEvent::getConsequences()
260
{
261
    if (consequences == NULL) {
262
        // similar to getCause
263
        long begin = clock();
264
        consequences = new IMessageDependencyList();
265
        std::list<BreadthSearchItem> todoList;
266
        todoList.push_back(BreadthSearchItem(getEvent(), NULL, FilteredMessageDependency::UNDEFINED, 0));
267

    
268
        // TODO: LONG RUNNING OPERATION
269
        // this is recursive and might take some time
270
        while (!todoList.empty()) {
271
            filteredEventLog->progress();
272
            if ((long)clock() - begin >= filteredEventLog->getMaximumConsequenceCollectionTime() * CLOCKS_PER_SEC / 1000)
273
                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
            FilteredMessageDependency::Kind currentKind = searchItem.effectiveKind;
282
            int level = searchItem.level;
283

    
284
            IMessageDependencyList *eventConsequences = currentEvent->getConsequences();
285
            for (IMessageDependencyList::iterator it = eventConsequences->begin(); it != eventConsequences->end(); it++) {
286
                IMessageDependency *messageDependency = *it;
287
                IEvent *consequenceEvent = messageDependency->getConsequenceEvent();
288

    
289
                if (consequenceEvent && (filteredEventLog->getCollectMessageReuses() || !dynamic_cast<MessageReuseDependency *>(messageDependency))) {
290
                    //printf("*** Checking at level %d for consequence event number %ld\n", level, consequenceEvent->getEventNumber());
291
                    FilteredMessageDependency::Kind effectiveKind = (FilteredMessageDependency::Kind)((int)currentKind | (int)getMessageDependencyKind(messageDependency));
292
                    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
                            pushNewFilteredMessageDependency(consequences, effectiveKind, beginMessageDependency, messageDependency);
299

    
300
                        if (countFilteredMessageDependencies(consequences) == filteredEventLog->getMaximumNumberOfConsequences())
301
                            return consequences;
302
                    }
303
                    else if (level < filteredEventLog->getMaximumConsequenceDepth())
304
                        todoList.push_back(BreadthSearchItem(consequenceEvent, level == 0 ? messageDependency : beginMessageDependency, effectiveKind, level + 1));
305
                }
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
void FilteredEvent::pushNewFilteredMessageDependency(IMessageDependencyList *messageDependencies, FilteredMessageDependency::Kind kind, IMessageDependency *beginMessageDependency, IMessageDependency *endMessageDependency)
324
{
325
    FilteredMessageDependency *newMessageDependency = new FilteredMessageDependency(filteredEventLog, kind,
326
            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
}