Statistics
| Branch: | Revision:

root / src / eventlog / event.cc @ 0ffda1dd

History | View | Annotate | Download (12.7 KB)

1
//=========================================================================
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
    eventEndEntry = NULL;
72
    moduleCreatedEntry = NULL;
73
    cause = NULL;
74
    causes = NULL;
75
    consequences = NULL;
76

    
77
    eventLogEntries.clear();
78
}
79

    
80
void Event::synchronize()
81
{
82
    if (consequences)
83
    {
84
        for (IMessageDependencyList::iterator it = consequences->begin(); it != consequences->end(); it++)
85
            delete *it;
86
        delete consequences;
87
        consequences = NULL;
88
    }
89
}
90

    
91
IEventLog *Event::getEventLog()
92
{
93
    return eventLog;
94
}
95

    
96
ModuleCreatedEntry *Event::getModuleCreatedEntry()
97
{
98
    if (!moduleCreatedEntry)
99
        moduleCreatedEntry = eventLog->getModuleCreatedEntry(getModuleId());
100

    
101
    return moduleCreatedEntry;
102
}
103

    
104
file_offset_t Event::parse(FileReader *reader, file_offset_t offset)
105
{
106
    eventLog->progress();
107

    
108
    deleteAllocatedObjects();
109
    numEventLogMessages = 0;
110
    numBeginSendEntries = 0;
111

    
112
    Assert(offset >= 0);
113
    beginOffset = offset;
114
    reader->seekTo(offset);
115

    
116
    if (PRINT_DEBUG_MESSAGES) printf("Parsing event at offset: %"INT64_PRINTF_FORMAT"d\n", offset);
117

    
118
    int index = 0;
119
    std::deque<int> contextModuleIds;
120

    
121
    while (true)
122
    {
123
        char *line = reader->getNextLineBufferPointer();
124

    
125
        if (!line) {
126
            Assert(eventEntry);
127
            endOffset = reader->getFileSize();
128
            return endOffset;
129
        }
130

    
131
        EventLogEntry *eventLogEntry = EventLogEntry::parseEntry(this, index, line, reader->getCurrentLineLength());
132

    
133
        // check for eventEndEntries. We do not include such entries in the eventLogEntries
134
        // for backwards compatibility with other plugins (e.g., eventTable)
135
        EventEndEntry * readEventEndEntry = dynamic_cast<EventEndEntry*>(eventLogEntry);
136
        if(readEventEndEntry) {
137
            eventEndEntry = readEventEndEntry;
138
            continue;
139
        }
140

    
141
        // skip empty lines
142
        if (!eventLogEntry)
143
            continue;
144
        else
145
            index++;
146

    
147
        // first line must be an event entry
148
        EventEntry *readEventEntry = dynamic_cast<EventEntry *>(eventLogEntry);
149
        if (!eventEntry) {
150
            Assert(readEventEntry);
151
            eventEntry = readEventEntry;
152
            contextModuleIds.push_front(eventEntry->moduleId);
153
        }
154
        else if (readEventEntry) {
155
            // stop at the start of the next event
156
            delete eventLogEntry;
157
            break;
158
        }
159

    
160
        Assert(eventEntry);
161

    
162
        // handle module method end
163
        ModuleMethodEndEntry *moduleMethodEndEntry = dynamic_cast<ModuleMethodEndEntry *>(eventLogEntry);
164
        if (moduleMethodEndEntry)
165
            contextModuleIds.pop_front();
166

    
167
        // store log entry
168
        eventLogEntry->level = contextModuleIds.size() - 1;
169
        eventLogEntry->contextModuleId = contextModuleIds.front();
170
        eventLogEntries.push_back(eventLogEntry);
171

    
172
        // handle module method begin
173
        ModuleMethodBeginEntry *moduleMethodBeginEntry = dynamic_cast<ModuleMethodBeginEntry *>(eventLogEntry);
174
        if (moduleMethodBeginEntry)
175
            contextModuleIds.push_front(moduleMethodBeginEntry->toModuleId);
176

    
177
        // count message entry
178
        if (dynamic_cast<EventLogMessageEntry *>(eventLogEntry))
179
            numEventLogMessages++;
180

    
181
        // count begin send entry
182
        if (dynamic_cast<BeginSendEntry *>(eventLogEntry))
183
            numBeginSendEntries++;
184
    }
185
    return endOffset = reader->getCurrentLineStartOffset();
186
}
187

    
188
void Event::print(FILE *file, bool outputEventLogMessages)
189
{
190
    for (EventLogEntryList::iterator it = eventLogEntries.begin(); it != eventLogEntries.end(); it++)
191
    {
192
        EventLogEntry *eventLogEntry = *it;
193

    
194
        if (outputEventLogMessages || !dynamic_cast<EventLogMessageEntry *>(eventLogEntry))
195
            eventLogEntry->print(file);
196
    }
197
}
198

    
199
EventLogMessageEntry *Event::getEventLogMessage(int index)
200
{
201
    Assert(index >= 0);
202

    
203
    for (EventLogEntryList::iterator it = eventLogEntries.begin(); it != eventLogEntries.end(); it++)
204
    {
205
        EventLogMessageEntry *eventLogMessage = dynamic_cast<EventLogMessageEntry *>(*it);
206

    
207
        if (eventLogMessage) {
208
            if (index == 0)
209
                return eventLogMessage;
210
            else
211
                index--;
212
        }
213
    }
214

    
215
    throw opp_runtime_error("index out of range");
216
}
217

    
218
bool Event::isSelfMessage(BeginSendEntry *beginSendEntry)
219
{
220
    Assert(beginSendEntry && this == beginSendEntry->getEvent());
221
    int index = beginSendEntry->getEntryIndex();
222

    
223
    if (index + 1 < (int)eventLogEntries.size())
224
        return dynamic_cast<EndSendEntry *>(eventLogEntries[index + 1]);
225
    else
226
        return false;
227
}
228

    
229
bool Event::isSelfMessageProcessingEvent()
230
{
231
    BeginSendEntry *beginSendEntry = getCauseBeginSendEntry();
232
    return beginSendEntry && beginSendEntry->getEvent()->isSelfMessage(beginSendEntry);
233
}
234

    
235
EndSendEntry *Event::getEndSendEntry(BeginSendEntry *beginSendEntry)
236
{
237
    Assert(beginSendEntry && this == beginSendEntry->getEvent());
238
    for (int i = beginSendEntry->getEntryIndex(); i < (int)eventLogEntries.size(); i++)
239
    {
240
        EventLogEntry *eventLogEntry = eventLogEntries[i];
241

    
242
        EndSendEntry *endSendEntry = dynamic_cast<EndSendEntry *>(eventLogEntry);
243
        if (endSendEntry)
244
            return endSendEntry;
245

    
246
        // message deleted on the channel (skip all deletes until the matching one is found)
247
        DeleteMessageEntry *deleteMessageEntry = dynamic_cast<DeleteMessageEntry *>(eventLogEntry);
248
        if (deleteMessageEntry && deleteMessageEntry->messageId == beginSendEntry->messageId) {
249
            return NULL;
250
        }
251
    }
252

    
253
    throw opp_runtime_error("Missing end message send or delete message entry");
254
}
255

    
256
simtime_t Event::getTransmissionDelay(BeginSendEntry *beginSendEntry)
257
{
258
    Assert(beginSendEntry && this == beginSendEntry->getEvent());
259
    EndSendEntry *endSendEntry = getEndSendEntry(beginSendEntry);
260
    int index = beginSendEntry->getEntryIndex();
261
    simtime_t transmissionDelay = BigDecimal::Zero;
262

    
263
    // there is at most one entry which specifies a transmission delay
264
    while (index < (int)eventLogEntries.size()) {
265
        EventLogEntry *eventLogEntry = eventLogEntries[++index];
266

    
267
        if (dynamic_cast<SendDirectEntry *>(eventLogEntry))
268
            transmissionDelay = ((SendDirectEntry *)eventLogEntry)->transmissionDelay;
269
        else if (dynamic_cast<SendHopEntry *>(eventLogEntry))
270
            transmissionDelay = ((SendHopEntry *)eventLogEntry)->transmissionDelay;
271
        else if (eventLogEntry == endSendEntry || !dynamic_cast<EventLogMessageEntry *>(eventLogEntry))
272
            break;
273

    
274
        if (transmissionDelay != 0)
275
            break;
276
    }
277

    
278
    return transmissionDelay;
279
}
280

    
281
Event *Event::getPreviousEvent()
282
{
283
    if (!previousEvent && eventLog->getFirstEvent() != this)
284
    {
285
        previousEvent = eventLog->getEventForEndOffset(beginOffset);
286

    
287
        if (previousEvent)
288
            IEvent::linkEvents(previousEvent, this);
289
    }
290

    
291
    return (Event *)previousEvent;
292
}
293

    
294
Event *Event::getNextEvent()
295
{
296
    if (!nextEvent && eventLog->getLastEvent() != this)
297
    {
298
        nextEvent = eventLog->getEventForBeginOffset(endOffset);
299

    
300
        if (nextEvent)
301
            Event::linkEvents(this, nextEvent);
302
    }
303

    
304
    return (Event *)nextEvent;
305
}
306

    
307
Event *Event::getCauseEvent()
308
{
309
    int causeEventNumber = getCauseEventNumber();
310

    
311
    if (causeEventNumber != -1)
312
        return eventLog->getEventForEventNumber(causeEventNumber);
313
    else
314
        return NULL;
315
}
316

    
317
BeginSendEntry *Event::getCauseBeginSendEntry()
318
{
319
    MessageDependency *cause = getCause();
320

    
321
    if (cause)
322
        return cause->getCauseBeginSendEntry();
323
    else
324
        return NULL;
325
}
326

    
327
MessageDependency *Event::getCause()
328
{
329
    if (!cause)
330
    {
331
        Event *event = getCauseEvent();
332

    
333
        if (event)
334
        {
335
            int beginSendEntryNumber = event->findBeginSendEntryIndex(getMessageId());
336

    
337
            if (beginSendEntryNumber != -1)
338
                cause = new MessageDependency(eventLog, false, getCauseEventNumber(), beginSendEntryNumber);
339
        }
340
    }
341

    
342
    return cause;
343
}
344

    
345
IMessageDependencyList *Event::getCauses()
346
{
347
    if (!causes)
348
    {
349
        causes = new IMessageDependencyList();
350

    
351
        if (getCause())
352
            // using "ce" from "E" line
353
            causes->push_back(getCause());
354

    
355
        // add message reuses
356
        for (int beginSendEntryNumber = 0; beginSendEntryNumber < (int)eventLogEntries.size(); beginSendEntryNumber++)
357
        {
358
            BeginSendEntry *beginSendEntry = dynamic_cast<BeginSendEntry *>(eventLogEntries[beginSendEntryNumber]);
359

    
360
            if (beginSendEntry &&
361
                beginSendEntry->previousEventNumber != -1 &&
362
                beginSendEntry->previousEventNumber != getEventNumber())
363
            {
364
                // store "pe" key from "BS" or "SA" lines
365
                causes->push_back(new MessageDependency(eventLog, true, getEventNumber(), beginSendEntryNumber));
366
                break;
367
            }
368
        }
369
    }
370

    
371
    return causes;
372
}
373

    
374
IMessageDependencyList *Event::getConsequences()
375
{
376
    if (!consequences)
377
    {
378
        consequences = new IMessageDependencyList();
379

    
380
        for (int beginSendEntryNumber = 0; beginSendEntryNumber < (int)eventLogEntries.size(); beginSendEntryNumber++)
381
        {
382
            EventLogEntry *eventLogEntry = eventLogEntries[beginSendEntryNumber];
383

    
384
            if (eventLogEntry->isMessageSend())
385
                // using "t" from "ES" lines
386
                consequences->push_back(new MessageDependency(eventLog, false, getEventNumber(), beginSendEntryNumber));
387
        }
388

    
389
        int beginSendEntryNumber;
390
        Event *reuserEvent = getReuserEvent(beginSendEntryNumber);
391

    
392
        if (reuserEvent != NULL && reuserEvent != this)
393
            consequences->push_back(new MessageDependency(eventLog, true, reuserEvent->getEventNumber(), beginSendEntryNumber));
394
    }
395

    
396
    return consequences;
397
}
398

    
399
Event *Event::getReuserEvent(int &beginSendEntryNumber)
400
{
401
    Event *current = this;
402

    
403
    // TODO: LONG RUNNING OPERATION
404
    // TODO: maybe the result of this calculation should be put into an index file lazily?
405
    // TODO: and first we should look it up there, so that the expensive computation is not repeated when the file is reopened
406
    // TODO: the limit on this loop should be configurable
407
    int maxLookAhead = 1000;
408
    while (current && maxLookAhead--) {
409
        eventLog->progress();
410

    
411
        for (beginSendEntryNumber = 0; beginSendEntryNumber < (int)current->eventLogEntries.size(); beginSendEntryNumber++)
412
        {
413
            EventLogEntry *eventLogEntry = current->eventLogEntries[beginSendEntryNumber];
414
            BeginSendEntry *beginSendEntry = dynamic_cast<BeginSendEntry *>(eventLogEntry);
415

    
416
            if (beginSendEntry && beginSendEntry->messageId == getMessageId())
417
            {
418
                if (beginSendEntry->previousEventNumber == getEventNumber())
419
                    return current;
420
                else
421
                    // events were filtered in between and this is not the first reuse
422
                    return NULL;
423
            }
424

    
425
            DeleteMessageEntry *deleteMessageEntry = dynamic_cast<DeleteMessageEntry *>(eventLogEntry);
426

    
427
            if (deleteMessageEntry && deleteMessageEntry->messageId == getMessageId()) {
428
                beginSendEntryNumber = -1;
429
                return NULL;
430
            }
431
        }
432

    
433
        current = current->getNextEvent();
434
    }
435

    
436
    beginSendEntryNumber = -1;
437
    return NULL;
438
}