Statistics
| Branch: | Revision:

root / src / eventlog / event.cc @ a3b7e786

History | View | Annotate | Download (12.8 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::getCauseEvent()
310
{
311
    int causeEventNumber = getCauseEventNumber();
312

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

    
319
BeginSendEntry *Event::getCauseBeginSendEntry()
320
{
321
    MessageDependency *cause = getCause();
322

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

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

    
335
        if (event)
336
        {
337
            int beginSendEntryNumber = event->findBeginSendEntryIndex(getMessageId());
338

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

    
344
    return cause;
345
}
346

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

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

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

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

    
373
    return causes;
374
}
375

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

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

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

    
391
        int beginSendEntryNumber;
392
        Event *reuserEvent = getReuserEvent(beginSendEntryNumber);
393

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

    
398
    return consequences;
399
}
400

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

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

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

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

    
427
            DeleteMessageEntry *deleteMessageEntry = dynamic_cast<DeleteMessageEntry *>(eventLogEntry);
428

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

    
435
        current = current->getNextEvent();
436
    }
437

    
438
    beginSendEntryNumber = -1;
439
    return NULL;
440
}