Statistics
| Branch: | Revision:

root / src / eventlog / event.cc @ 6b052c7a

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
    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
        // skip empty lines
134
        if (!eventLogEntry)
135
            continue;
136
        else
137
            index++;
138

    
139
        // first line must be an event entry
140
        EventEntry *readEventEntry = dynamic_cast<EventEntry *>(eventLogEntry);
141
        if (!eventEntry) {
142
            Assert(readEventEntry);
143
            eventEntry = readEventEntry;
144
            contextModuleIds.push_front(eventEntry->moduleId);
145
        }
146
        else if (readEventEntry) {
147
            // stop at the start of the next event
148
            delete eventLogEntry;
149
            break;
150
        }
151

    
152
        Assert(eventEntry);
153

    
154
        EventEndEntry * readEventEndEntry = dynamic_cast<EventEndEntry*>(eventLogEntry);
155

    
156
        if(readEventEndEntry) {
157
            eventEndEntry = readEventEndEntry;
158
            continue;
159
        }
160

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
277
    return transmissionDelay;
278
}
279

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

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

    
290
    return (Event *)previousEvent;
291
}
292

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

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

    
303
    return (Event *)nextEvent;
304
}
305

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

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

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

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

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

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

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

    
341
    return cause;
342
}
343

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

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

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

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

    
370
    return causes;
371
}
372

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

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

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

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

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

    
395
    return consequences;
396
}
397

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

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

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

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

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

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

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

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