Statistics
| Branch: | Revision:

root / src / eventlog / event.cc @ 12288d0e

History | View | Annotate | Download (13.4 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
    _earliestProcessingTime = 0;
80
}
81

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

    
93
IEventLog *Event::getEventLog()
94
{
95
    return eventLog;
96
}
97

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

    
103
    return moduleCreatedEntry;
104
}
105

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

    
110
    deleteAllocatedObjects();
111
    numEventLogMessages = 0;
112
    numBeginSendEntries = 0;
113

    
114
    Assert(offset >= 0);
115
    beginOffset = offset;
116
    reader->seekTo(offset);
117

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

    
120
    int index = 0;
121
    std::deque<int> contextModuleIds;
122

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

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

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

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

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

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

    
162
        Assert(eventEntry);
163

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

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

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

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

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

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

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

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

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

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

    
217
    throw opp_runtime_error("index out of range");
218
}
219

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

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

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

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

    
244
        EndSendEntry *endSendEntry = dynamic_cast<EndSendEntry *>(eventLogEntry);
245
        if (endSendEntry)
246
            return endSendEntry;
247

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

    
255
    throw opp_runtime_error("Missing end message send or delete message entry");
256
}
257

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

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

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

    
276
        if (transmissionDelay != 0)
277
            break;
278
    }
279

    
280
    return transmissionDelay;
281
}
282

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

    
289
        if (previousEvent)
290
            IEvent::linkEvents(previousEvent, this);
291
    }
292

    
293
    return (Event *)previousEvent;
294
}
295

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

    
302
        if (nextEvent)
303
            Event::linkEvents(this, nextEvent);
304
    }
305

    
306
    return (Event *)nextEvent;
307
}
308

    
309
Event *Event::getPreviousEventRealTime()
310
{
311
    if (eventLog->getFirstEventRealTime() == this) {
312
        return NULL;
313
    }
314
    Assert(previousEventRealTime != NULL);
315
    return (Event*)previousEventRealTime;
316
}
317

    
318
Event *Event::getNextEventRealTime()
319
{
320
    if (eventLog->getLastEventRealTime() == this) {
321
        return NULL;
322
    }
323
    Assert(nextEventRealTime != NULL);
324
    return (Event*)nextEventRealTime;
325
}
326

    
327
Event *Event::getCauseEvent()
328
{
329
    int causeEventNumber = getCauseEventNumber();
330

    
331
    if (causeEventNumber != -1)
332
        return eventLog->getEventForEventNumber(causeEventNumber);
333
    else
334
        return NULL;
335
}
336

    
337
BeginSendEntry *Event::getCauseBeginSendEntry()
338
{
339
    MessageDependency *cause = getCause();
340

    
341
    if (cause)
342
        return cause->getCauseBeginSendEntry();
343
    else
344
        return NULL;
345
}
346

    
347
MessageDependency *Event::getCause()
348
{
349
    if (!cause)
350
    {
351
        Event *event = getCauseEvent();
352

    
353
        if (event)
354
        {
355
            int beginSendEntryNumber = event->findBeginSendEntryIndex(getMessageId());
356

    
357
            if (beginSendEntryNumber != -1)
358
                cause = new MessageDependency(eventLog, false, getCauseEventNumber(), beginSendEntryNumber);
359
        }
360
    }
361

    
362
    return cause;
363
}
364

    
365
IMessageDependencyList *Event::getCauses()
366
{
367
    if (!causes)
368
    {
369
        causes = new IMessageDependencyList();
370

    
371
        if (getCause())
372
            // using "ce" from "E" line
373
            causes->push_back(getCause());
374

    
375
        // add message reuses
376
        for (int beginSendEntryNumber = 0; beginSendEntryNumber < (int)eventLogEntries.size(); beginSendEntryNumber++)
377
        {
378
            BeginSendEntry *beginSendEntry = dynamic_cast<BeginSendEntry *>(eventLogEntries[beginSendEntryNumber]);
379

    
380
            if (beginSendEntry &&
381
                beginSendEntry->previousEventNumber != -1 &&
382
                beginSendEntry->previousEventNumber != getEventNumber())
383
            {
384
                // store "pe" key from "BS" or "SA" lines
385
                causes->push_back(new MessageDependency(eventLog, true, getEventNumber(), beginSendEntryNumber));
386
                break;
387
            }
388
        }
389
    }
390

    
391
    return causes;
392
}
393

    
394
IMessageDependencyList *Event::getConsequences()
395
{
396
    if (!consequences)
397
    {
398
        consequences = new IMessageDependencyList();
399

    
400
        for (int beginSendEntryNumber = 0; beginSendEntryNumber < (int)eventLogEntries.size(); beginSendEntryNumber++)
401
        {
402
            EventLogEntry *eventLogEntry = eventLogEntries[beginSendEntryNumber];
403

    
404
            if (eventLogEntry->isMessageSend())
405
                // using "t" from "ES" lines
406
                consequences->push_back(new MessageDependency(eventLog, false, getEventNumber(), beginSendEntryNumber));
407
        }
408

    
409
        int beginSendEntryNumber;
410
        Event *reuserEvent = getReuserEvent(beginSendEntryNumber);
411

    
412
        if (reuserEvent != NULL && reuserEvent != this)
413
            consequences->push_back(new MessageDependency(eventLog, true, reuserEvent->getEventNumber(), beginSendEntryNumber));
414
    }
415

    
416
    return consequences;
417
}
418

    
419
Event *Event::getReuserEvent(int &beginSendEntryNumber)
420
{
421
    Event *current = this;
422

    
423
    // TODO: LONG RUNNING OPERATION
424
    // TODO: maybe the result of this calculation should be put into an index file lazily?
425
    // TODO: and first we should look it up there, so that the expensive computation is not repeated when the file is reopened
426
    // TODO: the limit on this loop should be configurable
427
    int maxLookAhead = 1000;
428
    while (current && maxLookAhead--) {
429
        eventLog->progress();
430

    
431
        for (beginSendEntryNumber = 0; beginSendEntryNumber < (int)current->eventLogEntries.size(); beginSendEntryNumber++)
432
        {
433
            EventLogEntry *eventLogEntry = current->eventLogEntries[beginSendEntryNumber];
434
            BeginSendEntry *beginSendEntry = dynamic_cast<BeginSendEntry *>(eventLogEntry);
435

    
436
            if (beginSendEntry && beginSendEntry->messageId == getMessageId())
437
            {
438
                if (beginSendEntry->previousEventNumber == getEventNumber())
439
                    return current;
440
                else
441
                    // events were filtered in between and this is not the first reuse
442
                    return NULL;
443
            }
444

    
445
            DeleteMessageEntry *deleteMessageEntry = dynamic_cast<DeleteMessageEntry *>(eventLogEntry);
446

    
447
            if (deleteMessageEntry && deleteMessageEntry->messageId == getMessageId()) {
448
                beginSendEntryNumber = -1;
449
                return NULL;
450
            }
451
        }
452

    
453
        current = current->getNextEvent();
454
    }
455

    
456
    beginSendEntryNumber = -1;
457
    return NULL;
458
}
459

    
460
long Event::getEarliestProcessingTime() {
461
    return _earliestProcessingTime;
462
}
463
long Event::getEarliestStartTime() {
464
    return ((_earliestProcessingTime == 0) ? 0 : _earliestProcessingTime - getComplexity());
465
}