Project

General

Profile

Statistics
| Branch: | Revision:

root / src / eventlog / event.cc @ a3be1d55

History | View | Annotate | Download (12.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
30
    clearInternalState();
31
}
32
33
Event::~Event()
34
{
35
    deleteAllocatedObjects();
36
}
37
38
void Event::deleteAllocatedObjects()
39
{
40
    for (EventLogEntryList::iterator it = eventLogEntries.begin(); it != eventLogEntries.end(); it++)
41
        delete *it;
42
43
    if (!cause)
44
        delete cause;
45
46
    if (causes)
47
    {
48
        for (IMessageDependencyList::iterator it = causes->begin(); it != causes->end(); it++)
49
            delete *it;
50
        delete causes;
51
    }
52
53
    if (consequences)
54
    {
55
        for (IMessageDependencyList::iterator it = consequences->begin(); it != consequences->end(); it++)
56
            delete *it;
57
        delete consequences;
58
    }
59
60
    clearInternalState();
61
}
62
63
void Event::clearInternalState()
64
{
65
    beginOffset = -1;
66
    endOffset = -1;
67
    numEventLogMessages = -1;
68
    numBeginSendEntries = -1;
69
70
    eventEntry = NULL;
71
    moduleCreatedEntry = NULL;
72
    cause = NULL;
73
    causes = NULL;
74
    consequences = NULL;
75
76
    eventLogEntries.clear();
77
}
78
79
void Event::synchronize()
80
{
81
    if (consequences)
82
    {
83
        for (IMessageDependencyList::iterator it = consequences->begin(); it != consequences->end(); it++)
84
            delete *it;
85
        delete consequences;
86
        consequences = NULL;
87
    }
88
}
89
90
IEventLog *Event::getEventLog()
91
{
92
    return eventLog;
93
}
94
95
ModuleCreatedEntry *Event::getModuleCreatedEntry()
96
{
97
    if (!moduleCreatedEntry)
98
        moduleCreatedEntry = eventLog->getModuleCreatedEntry(getModuleId());
99
100
    return moduleCreatedEntry;
101
}
102
103
file_offset_t Event::parse(FileReader *reader, file_offset_t offset)
104
{
105
    eventLog->progress();
106
107
    deleteAllocatedObjects();
108
    numEventLogMessages = 0;
109
    numBeginSendEntries = 0;
110
111
    Assert(offset >= 0);
112
    beginOffset = offset;
113
    reader->seekTo(offset);
114
115
    if (PRINT_DEBUG_MESSAGES) printf("Parsing event at offset: %"INT64_PRINTF_FORMAT"d\n", offset);
116
117
    int index = 0;
118
    std::deque<int> contextModuleIds;
119
120
    while (true)
121
    {
122
        char *line = reader->getNextLineBufferPointer();
123
124
        if (!line) {
125
            Assert(eventEntry);
126
            endOffset = reader->getFileSize();
127
            return endOffset;
128
        }
129
130
        EventLogEntry *eventLogEntry = EventLogEntry::parseEntry(this, index, line, reader->getCurrentLineLength());
131
132
        // skip empty lines
133
        if (!eventLogEntry)
134
            continue;
135
        else
136
            index++;
137
138
        // first line must be an event entry
139
        EventEntry *readEventEntry = dynamic_cast<EventEntry *>(eventLogEntry);
140
        if (!eventEntry) {
141
            Assert(readEventEntry);
142
            eventEntry = readEventEntry;
143
            contextModuleIds.push_front(eventEntry->moduleId);
144
        }
145
        else if (readEventEntry) {
146
            // stop at the start of the next event
147
            delete eventLogEntry;
148
            break;
149
        }
150
151
        Assert(eventEntry);
152
153
        // handle module method end
154
        ModuleMethodEndEntry *moduleMethodEndEntry = dynamic_cast<ModuleMethodEndEntry *>(eventLogEntry);
155
        if (moduleMethodEndEntry)
156
            contextModuleIds.pop_front();
157
158
        // store log entry
159
        eventLogEntry->level = contextModuleIds.size() - 1;
160
        eventLogEntry->contextModuleId = contextModuleIds.front();
161
        eventLogEntries.push_back(eventLogEntry);
162
163
        // handle module method begin
164
        ModuleMethodBeginEntry *moduleMethodBeginEntry = dynamic_cast<ModuleMethodBeginEntry *>(eventLogEntry);
165
        if (moduleMethodBeginEntry)
166
            contextModuleIds.push_front(moduleMethodBeginEntry->toModuleId);
167
168
        // count message entry
169
        if (dynamic_cast<EventLogMessageEntry *>(eventLogEntry))
170
            numEventLogMessages++;
171
172
        // count begin send entry
173
        if (dynamic_cast<BeginSendEntry *>(eventLogEntry))
174
            numBeginSendEntries++;
175
    }
176
177
    return endOffset = reader->getCurrentLineStartOffset();
178
}
179
180
void Event::print(FILE *file, bool outputEventLogMessages)
181
{
182
    for (EventLogEntryList::iterator it = eventLogEntries.begin(); it != eventLogEntries.end(); it++)
183
    {
184
        EventLogEntry *eventLogEntry = *it;
185
186
        if (outputEventLogMessages || !dynamic_cast<EventLogMessageEntry *>(eventLogEntry))
187
            eventLogEntry->print(file);
188
    }
189
}
190
191
EventLogMessageEntry *Event::getEventLogMessage(int index)
192
{
193
    Assert(index >= 0);
194
195
    for (EventLogEntryList::iterator it = eventLogEntries.begin(); it != eventLogEntries.end(); it++)
196
    {
197
        EventLogMessageEntry *eventLogMessage = dynamic_cast<EventLogMessageEntry *>(*it);
198
199
        if (eventLogMessage) {
200
            if (index == 0)
201
                return eventLogMessage;
202
            else
203
                index--;
204
        }
205
    }
206
207
    throw opp_runtime_error("index out of range");
208
}
209
210
bool Event::isSelfMessage(BeginSendEntry *beginSendEntry)
211
{
212
    Assert(beginSendEntry && this == beginSendEntry->getEvent());
213
    int index = beginSendEntry->getEntryIndex();
214
215
    if (index + 1 < (int)eventLogEntries.size())
216
        return dynamic_cast<EndSendEntry *>(eventLogEntries[index + 1]);
217
    else
218
        return false;
219
}
220
221
bool Event::isSelfMessageProcessingEvent()
222
{
223
    BeginSendEntry *beginSendEntry = getCauseBeginSendEntry();
224
    return beginSendEntry && beginSendEntry->getEvent()->isSelfMessage(beginSendEntry);
225
}
226
227
EndSendEntry *Event::getEndSendEntry(BeginSendEntry *beginSendEntry)
228
{
229
    Assert(beginSendEntry && this == beginSendEntry->getEvent());
230
    for (int i = beginSendEntry->getEntryIndex(); i < (int)eventLogEntries.size(); i++)
231
    {
232
        EventLogEntry *eventLogEntry = eventLogEntries[i];
233
234
        EndSendEntry *endSendEntry = dynamic_cast<EndSendEntry *>(eventLogEntry);
235
        if (endSendEntry)
236
            return endSendEntry;
237
238
        // message deleted on the channel (skip all deletes until the matching one is found)
239
        DeleteMessageEntry *deleteMessageEntry = dynamic_cast<DeleteMessageEntry *>(eventLogEntry);
240
        if (deleteMessageEntry && deleteMessageEntry->messageId == beginSendEntry->messageId) {
241
            return NULL;
242
        }
243
    }
244
245
    throw opp_runtime_error("Missing end message send or delete message entry");
246
}
247
248
simtime_t Event::getTransmissionDelay(BeginSendEntry *beginSendEntry)
249
{
250
    Assert(beginSendEntry && this == beginSendEntry->getEvent());
251
    EndSendEntry *endSendEntry = getEndSendEntry(beginSendEntry);
252
    int index = beginSendEntry->getEntryIndex();
253
    simtime_t transmissionDelay = BigDecimal::Zero;
254
255
    // there is at most one entry which specifies a transmission delay
256
    while (index < (int)eventLogEntries.size()) {
257
        EventLogEntry *eventLogEntry = eventLogEntries[++index];
258
259
        if (dynamic_cast<SendDirectEntry *>(eventLogEntry))
260
            transmissionDelay = ((SendDirectEntry *)eventLogEntry)->transmissionDelay;
261
        else if (dynamic_cast<SendHopEntry *>(eventLogEntry))
262
            transmissionDelay = ((SendHopEntry *)eventLogEntry)->transmissionDelay;
263
        else if (eventLogEntry == endSendEntry || !dynamic_cast<EventLogMessageEntry *>(eventLogEntry))
264
            break;
265
266
        if (transmissionDelay != 0)
267
            break;
268
    }
269
270
    return transmissionDelay;
271
}
272
273
Event *Event::getPreviousEvent()
274
{
275
    if (!previousEvent && eventLog->getFirstEvent() != this)
276
    {
277
        previousEvent = eventLog->getEventForEndOffset(beginOffset);
278
279
        if (previousEvent)
280
            IEvent::linkEvents(previousEvent, this);
281
    }
282
283
    return (Event *)previousEvent;
284
}
285
286
Event *Event::getNextEvent()
287
{
288
    if (!nextEvent && eventLog->getLastEvent() != this)
289
    {
290
        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
303
    if (causeEventNumber != -1)
304
        return eventLog->getEventForEventNumber(causeEventNumber);
305
    else
306
        return NULL;
307
}
308
309
BeginSendEntry *Event::getCauseBeginSendEntry()
310
{
311
    MessageDependency *cause = getCause();
312
313
    if (cause)
314
        return cause->getCauseBeginSendEntry();
315
    else
316
        return NULL;
317
}
318
319
MessageDependency *Event::getCause()
320
{
321
    if (!cause)
322
    {
323
        Event *event = getCauseEvent();
324
325
        if (event)
326
        {
327
            int beginSendEntryNumber = event->findBeginSendEntryIndex(getMessageId());
328
329
            if (beginSendEntryNumber != -1)
330
                cause = new MessageDependency(eventLog, false, getCauseEventNumber(), beginSendEntryNumber);
331
        }
332
    }
333
334
    return cause;
335
}
336
337
IMessageDependencyList *Event::getCauses()
338
{
339
    if (!causes)
340
    {
341
        causes = new IMessageDependencyList();
342
343
        if (getCause())
344
            // using "ce" from "E" line
345
            causes->push_back(getCause());
346
347
        // add message reuses
348
        for (int beginSendEntryNumber = 0; beginSendEntryNumber < (int)eventLogEntries.size(); beginSendEntryNumber++)
349
        {
350
            BeginSendEntry *beginSendEntry = dynamic_cast<BeginSendEntry *>(eventLogEntries[beginSendEntryNumber]);
351
352
            if (beginSendEntry &&
353
                beginSendEntry->previousEventNumber != -1 &&
354
                beginSendEntry->previousEventNumber != getEventNumber())
355
            {
356
                // store "pe" key from "BS" or "SA" lines
357
                causes->push_back(new MessageDependency(eventLog, true, getEventNumber(), beginSendEntryNumber));
358
                break;
359
            }
360
        }
361
    }
362
363
    return causes;
364
}
365
366
IMessageDependencyList *Event::getConsequences()
367
{
368
    if (!consequences)
369
    {
370
        consequences = new IMessageDependencyList();
371
372
        for (int beginSendEntryNumber = 0; beginSendEntryNumber < (int)eventLogEntries.size(); beginSendEntryNumber++)
373
        {
374
            EventLogEntry *eventLogEntry = eventLogEntries[beginSendEntryNumber];
375
376
            if (eventLogEntry->isMessageSend())
377
                // using "t" from "ES" lines
378
                consequences->push_back(new MessageDependency(eventLog, false, getEventNumber(), beginSendEntryNumber));
379
        }
380
381
        int beginSendEntryNumber;
382
        Event *reuserEvent = getReuserEvent(beginSendEntryNumber);
383
384
        if (reuserEvent != NULL && reuserEvent != this)
385
            consequences->push_back(new MessageDependency(eventLog, true, reuserEvent->getEventNumber(), beginSendEntryNumber));
386
    }
387
388
    return consequences;
389
}
390
391
Event *Event::getReuserEvent(int &beginSendEntryNumber)
392
{
393
    Event *current = this;
394
395
    // TODO: LONG RUNNING OPERATION
396
    // TODO: maybe the result of this calculation should be put into an index file lazily?
397
    // TODO: and first we should look it up there, so that the expensive computation is not repeated when the file is reopened
398
    // TODO: the limit on this loop should be configurable
399
    int maxLookAhead = 1000;
400
    while (current && maxLookAhead--) {
401
        eventLog->progress();
402
403
        for (beginSendEntryNumber = 0; beginSendEntryNumber < (int)current->eventLogEntries.size(); beginSendEntryNumber++)
404
        {
405
            EventLogEntry *eventLogEntry = current->eventLogEntries[beginSendEntryNumber];
406
            BeginSendEntry *beginSendEntry = dynamic_cast<BeginSendEntry *>(eventLogEntry);
407
408
            if (beginSendEntry && beginSendEntry->messageId == getMessageId())
409
            {
410
                if (beginSendEntry->previousEventNumber == getEventNumber())
411
                    return current;
412
                else
413
                    // events were filtered in between and this is not the first reuse
414
                    return NULL;
415
            }
416
417
            DeleteMessageEntry *deleteMessageEntry = dynamic_cast<DeleteMessageEntry *>(eventLogEntry);
418
419
            if (deleteMessageEntry && deleteMessageEntry->messageId == getMessageId()) {
420
                beginSendEntryNumber = -1;
421
                return NULL;
422
            }
423
        }
424
425
        current = current->getNextEvent();
426
    }
427
428
    beginSendEntryNumber = -1;
429
    return NULL;
430
}