Statistics
| Branch: | Revision:

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

History | View | Annotate | Download (11.4 KB)

1 01873262 Georg Kunz
//=========================================================================
2
//  EVENT.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 "deque"
19
#include "filereader.h"
20
#include "event.h"
21
#include "eventlog.h"
22
#include "eventlogentry.h"
23
24
USING_NAMESPACE
25
26
Event::Event(EventLog *eventLog)
27
{
28
    this->eventLog = eventLog;
29
    clearInternalState();
30
}
31
32
Event::~Event()
33
{
34
    deleteAllocatedObjects();
35
}
36
37
void Event::clearInternalState()
38
{
39
    beginOffset = -1;
40
    endOffset = -1;
41
    numEventLogMessages = -1;
42
    numBeginSendEntries = -1;
43
    eventEntry = NULL;
44
    moduleCreatedEntry = NULL;
45
    cause = NULL;
46
    causes = NULL;
47
    consequences = NULL;
48
    eventLogEntries.clear();
49
}
50
51 3027cc88 Mirko Stoffers
void Event::deleteConsequences()
52 01873262 Georg Kunz
{
53 3027cc88 Mirko Stoffers
    if (consequences) {
54 01873262 Georg Kunz
        for (IMessageDependencyList::iterator it = consequences->begin(); it != consequences->end(); it++)
55
            delete *it;
56
        delete consequences;
57
        consequences = NULL;
58
    }
59
}
60
61 3027cc88 Mirko Stoffers
void Event::deleteAllocatedObjects()
62
{
63
    if (cause && !causes) {
64
        delete cause;
65
        cause = NULL;
66
    }
67
    if (causes) {
68
        for (IMessageDependencyList::iterator it = causes->begin(); it != causes->end(); it++)
69
            delete *it;
70
        delete causes;
71
        causes = NULL;
72
    }
73
    deleteConsequences();
74
    for (EventLogEntryList::iterator it = eventLogEntries.begin(); it != eventLogEntries.end(); it++)
75
        delete *it;
76
    eventLogEntries.clear();
77
}
78
79
void Event::synchronize(FileReader::FileChangedState change)
80
{
81
    if (change != FileReader::UNCHANGED) {
82
        IEvent::synchronize(change);
83
        switch (change) {
84
            case FileReader::OVERWRITTEN:
85
                deleteAllocatedObjects();
86
                clearInternalState();
87
                break;
88
            case FileReader::APPENDED:
89
                deleteConsequences();
90
                break;
91
            case FileReader::UNCHANGED:   // just to avoid unused enumeration value warnings
92
                break;
93
        }
94
    }
95
}
96
97 01873262 Georg Kunz
IEventLog *Event::getEventLog()
98
{
99
    return eventLog;
100
}
101
102
ModuleCreatedEntry *Event::getModuleCreatedEntry()
103
{
104
    if (!moduleCreatedEntry)
105
        moduleCreatedEntry = eventLog->getModuleCreatedEntry(getModuleId());
106
107
    return moduleCreatedEntry;
108
}
109
110
file_offset_t Event::parse(FileReader *reader, file_offset_t offset)
111
{
112
    eventLog->progress();
113
114
    deleteAllocatedObjects();
115 3027cc88 Mirko Stoffers
    clearInternalState();
116 01873262 Georg Kunz
    numEventLogMessages = 0;
117
    numBeginSendEntries = 0;
118
119
    Assert(offset >= 0);
120
    beginOffset = offset;
121
    reader->seekTo(offset);
122
123
    if (PRINT_DEBUG_MESSAGES) printf("Parsing event at offset: %"INT64_PRINTF_FORMAT"d\n", offset);
124
125
    int index = 0;
126
    std::deque<int> contextModuleIds;
127
128 3027cc88 Mirko Stoffers
    while (true) {
129 01873262 Georg Kunz
        char *line = reader->getNextLineBufferPointer();
130
131
        if (!line) {
132
            Assert(eventEntry);
133
            endOffset = reader->getFileSize();
134
            return endOffset;
135
        }
136
137 3027cc88 Mirko Stoffers
        EventLogEntry *eventLogEntry = EventLogEntry::parseEntry(eventLog, this, index, reader->getCurrentLineStartOffset(), line, reader->getCurrentLineLength());
138 01873262 Georg Kunz
139
        // skip empty lines
140
        if (!eventLogEntry)
141
            continue;
142
        else
143
            index++;
144
145
        // first line must be an event entry
146
        EventEntry *readEventEntry = dynamic_cast<EventEntry *>(eventLogEntry);
147
        if (!eventEntry) {
148
            Assert(readEventEntry);
149
            eventEntry = readEventEntry;
150
            contextModuleIds.push_front(eventEntry->moduleId);
151
        }
152
        else if (readEventEntry) {
153
            // stop at the start of the next event
154
            delete eventLogEntry;
155
            break;
156
        }
157
158
        Assert(eventEntry);
159
160
        // handle module method end
161
        ModuleMethodEndEntry *moduleMethodEndEntry = dynamic_cast<ModuleMethodEndEntry *>(eventLogEntry);
162
        if (moduleMethodEndEntry)
163
            contextModuleIds.pop_front();
164
165
        // store log entry
166
        eventLogEntry->level = contextModuleIds.size() - 1;
167
        eventLogEntry->contextModuleId = contextModuleIds.front();
168
        eventLogEntries.push_back(eventLogEntry);
169
170
        // handle module method begin
171
        ModuleMethodBeginEntry *moduleMethodBeginEntry = dynamic_cast<ModuleMethodBeginEntry *>(eventLogEntry);
172
        if (moduleMethodBeginEntry)
173
            contextModuleIds.push_front(moduleMethodBeginEntry->toModuleId);
174
175
        // count message entry
176
        if (dynamic_cast<EventLogMessageEntry *>(eventLogEntry))
177
            numEventLogMessages++;
178
179
        // count begin send entry
180
        if (dynamic_cast<BeginSendEntry *>(eventLogEntry))
181
            numBeginSendEntries++;
182
    }
183 842775ab Mirko Stoffers
184 3027cc88 Mirko Stoffers
    Assert(eventEntry);
185 01873262 Georg Kunz
    return endOffset = reader->getCurrentLineStartOffset();
186
}
187
188
void Event::print(FILE *file, bool outputEventLogMessages)
189
{
190 3027cc88 Mirko Stoffers
    for (EventLogEntryList::iterator it = eventLogEntries.begin(); it != eventLogEntries.end(); it++) {
191 01873262 Georg Kunz
        EventLogEntry *eventLogEntry = *it;
192
        if (outputEventLogMessages || !dynamic_cast<EventLogMessageEntry *>(eventLogEntry))
193
            eventLogEntry->print(file);
194
    }
195
}
196
197
EventLogMessageEntry *Event::getEventLogMessage(int index)
198
{
199
    Assert(index >= 0);
200
201 3027cc88 Mirko Stoffers
    for (EventLogEntryList::iterator it = eventLogEntries.begin(); it != eventLogEntries.end(); it++) {
202 01873262 Georg Kunz
        EventLogMessageEntry *eventLogMessage = dynamic_cast<EventLogMessageEntry *>(*it);
203
204
        if (eventLogMessage) {
205
            if (index == 0)
206
                return eventLogMessage;
207
            else
208
                index--;
209
        }
210
    }
211
212
    throw opp_runtime_error("index out of range");
213
}
214
215
bool Event::isSelfMessage(BeginSendEntry *beginSendEntry)
216
{
217
    Assert(beginSendEntry && this == beginSendEntry->getEvent());
218
    int index = beginSendEntry->getEntryIndex();
219
220
    if (index + 1 < (int)eventLogEntries.size())
221
        return dynamic_cast<EndSendEntry *>(eventLogEntries[index + 1]);
222
    else
223
        return false;
224
}
225
226
bool Event::isSelfMessageProcessingEvent()
227
{
228
    BeginSendEntry *beginSendEntry = getCauseBeginSendEntry();
229
    return beginSendEntry && beginSendEntry->getEvent()->isSelfMessage(beginSendEntry);
230
}
231
232
EndSendEntry *Event::getEndSendEntry(BeginSendEntry *beginSendEntry)
233
{
234
    Assert(beginSendEntry && this == beginSendEntry->getEvent());
235 3027cc88 Mirko Stoffers
    for (int i = beginSendEntry->getEntryIndex(); i < (int)eventLogEntries.size(); i++) {
236 01873262 Georg Kunz
        EventLogEntry *eventLogEntry = eventLogEntries[i];
237
238
        EndSendEntry *endSendEntry = dynamic_cast<EndSendEntry *>(eventLogEntry);
239
        if (endSendEntry)
240
            return endSendEntry;
241
242
        // message deleted on the channel (skip all deletes until the matching one is found)
243
        DeleteMessageEntry *deleteMessageEntry = dynamic_cast<DeleteMessageEntry *>(eventLogEntry);
244 3027cc88 Mirko Stoffers
        if (deleteMessageEntry && deleteMessageEntry->messageId == beginSendEntry->messageId)
245 01873262 Georg Kunz
            return NULL;
246
    }
247
248 3027cc88 Mirko Stoffers
    throw opp_runtime_error("neither EndSendEntry nor DeleteMessageEntry found");
249 01873262 Georg Kunz
}
250
251
simtime_t Event::getTransmissionDelay(BeginSendEntry *beginSendEntry)
252
{
253
    Assert(beginSendEntry && this == beginSendEntry->getEvent());
254
    EndSendEntry *endSendEntry = getEndSendEntry(beginSendEntry);
255 3027cc88 Mirko Stoffers
    int index = beginSendEntry->getEntryIndex() + 1;
256 01873262 Georg Kunz
    simtime_t transmissionDelay = BigDecimal::Zero;
257
258
    // there is at most one entry which specifies a transmission delay
259
    while (index < (int)eventLogEntries.size()) {
260 3027cc88 Mirko Stoffers
        EventLogEntry *eventLogEntry = eventLogEntries[index];
261 01873262 Georg Kunz
        if (dynamic_cast<SendDirectEntry *>(eventLogEntry))
262
            transmissionDelay = ((SendDirectEntry *)eventLogEntry)->transmissionDelay;
263
        else if (dynamic_cast<SendHopEntry *>(eventLogEntry))
264
            transmissionDelay = ((SendHopEntry *)eventLogEntry)->transmissionDelay;
265
        else if (eventLogEntry == endSendEntry || !dynamic_cast<EventLogMessageEntry *>(eventLogEntry))
266
            break;
267
        if (transmissionDelay != 0)
268
            break;
269 3027cc88 Mirko Stoffers
        index++;
270 01873262 Georg Kunz
    }
271
272
    return transmissionDelay;
273
}
274
275
Event *Event::getPreviousEvent()
276
{
277 3027cc88 Mirko Stoffers
    if (!previousEvent && eventLog->getFirstEvent() != this) {
278 01873262 Georg Kunz
        previousEvent = eventLog->getEventForEndOffset(beginOffset);
279
280
        if (previousEvent)
281
            IEvent::linkEvents(previousEvent, this);
282
    }
283
284
    return (Event *)previousEvent;
285
}
286
287
Event *Event::getNextEvent()
288
{
289 3027cc88 Mirko Stoffers
    if (!nextEvent && eventLog->getLastEvent() != this) {
290 01873262 Georg Kunz
        nextEvent = eventLog->getEventForBeginOffset(endOffset);
291
292
        if (nextEvent)
293
            Event::linkEvents(this, nextEvent);
294
    }
295
296
    return (Event *)nextEvent;
297
}
298
299
Event *Event::getCauseEvent()
300
{
301
    int causeEventNumber = getCauseEventNumber();
302
    if (causeEventNumber != -1)
303
        return eventLog->getEventForEventNumber(causeEventNumber);
304
    else
305
        return NULL;
306
}
307
308
BeginSendEntry *Event::getCauseBeginSendEntry()
309
{
310 3027cc88 Mirko Stoffers
    MessageSendDependency *cause = getCause();
311 01873262 Georg Kunz
    if (cause)
312 3027cc88 Mirko Stoffers
        return (BeginSendEntry *)cause->getMessageEntry();
313 01873262 Georg Kunz
    else
314
        return NULL;
315
}
316
317 3027cc88 Mirko Stoffers
MessageSendDependency *Event::getCause()
318 01873262 Georg Kunz
{
319 3027cc88 Mirko Stoffers
    if (!cause) {
320 01873262 Georg Kunz
        Event *event = getCauseEvent();
321 3027cc88 Mirko Stoffers
        if (event) {
322 01873262 Georg Kunz
            int beginSendEntryNumber = event->findBeginSendEntryIndex(getMessageId());
323
            if (beginSendEntryNumber != -1)
324 3027cc88 Mirko Stoffers
                cause = new MessageSendDependency(eventLog, getCauseEventNumber(), beginSendEntryNumber);
325 01873262 Georg Kunz
        }
326
    }
327
    return cause;
328
}
329
330
IMessageDependencyList *Event::getCauses()
331
{
332 3027cc88 Mirko Stoffers
    if (!causes) {
333 01873262 Georg Kunz
        causes = new IMessageDependencyList();
334
335
        if (getCause())
336
            // using "ce" from "E" line
337
            causes->push_back(getCause());
338
339
        // add message reuses
340 3027cc88 Mirko Stoffers
        eventnumber_t eventNumber = getEventNumber();
341
        for (int i = 0; i < (int)eventLogEntries.size(); i++) {
342
            EventLogEntry *eventLogEntry = eventLogEntries[i];
343
            MessageEntry *messageEntry = dynamic_cast<MessageEntry *>(eventLogEntry);
344
            if (messageEntry && messageEntry->previousEventNumber != -1 && messageEntry->previousEventNumber != eventNumber)
345
                causes->push_back(new MessageReuseDependency(eventLog, eventNumber, i));
346 01873262 Georg Kunz
        }
347
    }
348
349
    return causes;
350
}
351
352
IMessageDependencyList *Event::getConsequences()
353
{
354 3027cc88 Mirko Stoffers
    if (!consequences) {
355 01873262 Georg Kunz
        consequences = new IMessageDependencyList();
356 3027cc88 Mirko Stoffers
        for (int beginSendEntryNumber = 0; beginSendEntryNumber < (int)eventLogEntries.size(); beginSendEntryNumber++) {
357 01873262 Georg Kunz
            EventLogEntry *eventLogEntry = eventLogEntries[beginSendEntryNumber];
358 3027cc88 Mirko Stoffers
            if (dynamic_cast<BeginSendEntry *>(eventLogEntry))
359 01873262 Georg Kunz
                // using "t" from "ES" lines
360 3027cc88 Mirko Stoffers
                consequences->push_back(new MessageSendDependency(eventLog, getEventNumber(), beginSendEntryNumber));
361 01873262 Georg Kunz
        }
362 3027cc88 Mirko Stoffers
        std::vector<MessageEntry *> messageEntries = eventLog->getMessageEntriesWithPreviousEventNumber(getEventNumber());
363
        for (int i = 0; i < (int)messageEntries.size(); i++) {
364
            MessageEntry *messageEntry = messageEntries[i];
365
            Assert(messageEntry->previousEventNumber == getEventNumber());
366
            consequences->push_back(new MessageReuseDependency(eventLog, messageEntry->getEvent()->getEventNumber(), messageEntry->getEntryIndex()));
367 01873262 Georg Kunz
        }
368
    }
369 3027cc88 Mirko Stoffers
    return consequences;
370 01873262 Georg Kunz
}