Statistics
| Branch: | Revision:

root / src / eventlog / event.cc @ 2f5cc443

History | View | Annotate | Download (12.5 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
        }
158

    
159
        // handle module method end
160
        ModuleMethodEndEntry *moduleMethodEndEntry = dynamic_cast<ModuleMethodEndEntry *>(eventLogEntry);
161
        if (moduleMethodEndEntry)
162
            contextModuleIds.pop_front();
163

    
164
        // store log entry
165
        eventLogEntry->level = contextModuleIds.size() - 1;
166
        eventLogEntry->contextModuleId = contextModuleIds.front();
167
        eventLogEntries.push_back(eventLogEntry);
168

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

    
174
        // count message entry
175
        if (dynamic_cast<EventLogMessageEntry *>(eventLogEntry))
176
            numEventLogMessages++;
177

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

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

    
191
        if (outputEventLogMessages || !dynamic_cast<EventLogMessageEntry *>(eventLogEntry))
192
            eventLogEntry->print(file);
193
    }
194
}
195

    
196
EventLogMessageEntry *Event::getEventLogMessage(int index)
197
{
198
    Assert(index >= 0);
199

    
200
    for (EventLogEntryList::iterator it = eventLogEntries.begin(); it != eventLogEntries.end(); it++)
201
    {
202
        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
    for (int i = beginSendEntry->getEntryIndex(); i < (int)eventLogEntries.size(); i++)
236
    {
237
        EventLogEntry *eventLogEntry = eventLogEntries[i];
238

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

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

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

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

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

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

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

    
275
    return transmissionDelay;
276
}
277

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

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

    
288
    return (Event *)previousEvent;
289
}
290

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

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

    
301
    return (Event *)nextEvent;
302
}
303

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

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

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

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

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

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

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

    
339
    return cause;
340
}
341

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

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

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

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

    
368
    return causes;
369
}
370

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

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

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

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

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

    
393
    return consequences;
394
}
395

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

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

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

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

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

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

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

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