Statistics
| Branch: | Revision:

root / src / eventlog / event.cc @ 61338f86

History | View | Annotate | Download (12.6 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
    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
        EventEndEntry * readEventEndEntry = dynamic_cast<EventEndEntry*>(eventLogEntry);
154

    
155
        if(readEventEndEntry) {
156
            eventEndEntry = readEventEndEntry;
157
            continue;
158
        }
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
    return endOffset = reader->getCurrentLineStartOffset();
184
}
185

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

    
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
    for (EventLogEntryList::iterator it = eventLogEntries.begin(); it != eventLogEntries.end(); it++)
202
    {
203
        EventLogMessageEntry *eventLogMessage = dynamic_cast<EventLogMessageEntry *>(*it);
204

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

    
213
    throw opp_runtime_error("index out of range");
214
}
215

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

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

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

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

    
240
        EndSendEntry *endSendEntry = dynamic_cast<EndSendEntry *>(eventLogEntry);
241
        if (endSendEntry)
242
            return endSendEntry;
243

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

    
251
    throw opp_runtime_error("Missing end message send or delete message entry");
252
}
253

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

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

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

    
272
        if (transmissionDelay != 0)
273
            break;
274
    }
275

    
276
    return transmissionDelay;
277
}
278

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

    
285
        if (previousEvent)
286
            IEvent::linkEvents(previousEvent, this);
287
    }
288

    
289
    return (Event *)previousEvent;
290
}
291

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

    
298
        if (nextEvent)
299
            Event::linkEvents(this, nextEvent);
300
    }
301

    
302
    return (Event *)nextEvent;
303
}
304

    
305
Event *Event::getCauseEvent()
306
{
307
    int causeEventNumber = getCauseEventNumber();
308

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

    
315
BeginSendEntry *Event::getCauseBeginSendEntry()
316
{
317
    MessageDependency *cause = getCause();
318

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

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

    
331
        if (event)
332
        {
333
            int beginSendEntryNumber = event->findBeginSendEntryIndex(getMessageId());
334

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

    
340
    return cause;
341
}
342

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

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

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

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

    
369
    return causes;
370
}
371

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

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

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

    
387
        int beginSendEntryNumber;
388
        Event *reuserEvent = getReuserEvent(beginSendEntryNumber);
389

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

    
394
    return consequences;
395
}
396

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

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

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

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

    
423
            DeleteMessageEntry *deleteMessageEntry = dynamic_cast<DeleteMessageEntry *>(eventLogEntry);
424

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

    
431
        current = current->getNextEvent();
432
    }
433

    
434
    beginSendEntryNumber = -1;
435
    return NULL;
436
}