Statistics
| Branch: | Revision:

root / src / eventlog / eventlog.cc @ 842775ab

History | View | Annotate | Download (18.3 KB)

1
//=========================================================================
2
//  EVENTLOG.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 "filereader.h"
19
#include "stringpool.h"
20
#include "eventlog.h"
21

    
22
NAMESPACE_BEGIN
23

    
24
CommonStringPool eventLogStringPool;
25

    
26
EventLog::EventLog(FileReader *reader) : EventLogIndex(reader)
27
{
28
    reader->setIgnoreAppendChanges(false);
29
    clearInternalState();
30
    parseKeyframes();
31
}
32

    
33
EventLog::~EventLog()
34
{
35
    deleteAllocatedObjects();
36
}
37

    
38
void EventLog::clearInternalState()
39
{
40
    numParsedEvents = 0;
41
    approximateNumberOfEvents = -1;
42
    progressCallInterval = CLOCKS_PER_SEC;
43
    lastProgressCall = -1;
44
    firstEvent = NULL;
45
    lastEvent = NULL;
46
    messageNames.clear();
47
    messageClassNames.clear();
48
    moduleIdToModuleCreatedEntryMap.clear();
49
    moduleIdAndGateIdToGateCreatedEntryMap.clear();
50
    previousEventNumberToMessageEntriesMap.clear();
51
    simulationBeginEntry = NULL;
52
    simulationEndEntry = NULL;
53
    eventNumberToEventMap.clear();
54
    beginOffsetToEventMap.clear();
55
    endOffsetToEventMap.clear();
56
    consequenceLookaheadLimits.clear();
57
    previousEventNumberToMessageEntriesMap.clear();
58
}
59

    
60
void EventLog::deleteAllocatedObjects()
61
{
62
    for (EventNumberToEventMap::iterator it = eventNumberToEventMap.begin(); it != eventNumberToEventMap.end(); it++)
63
        delete it->second;
64
}
65

    
66
void EventLog::synchronize(FileReader::FileChangedState change)
67
{
68
    if (change != FileReader::UNCHANGED) {
69
        IEventLog::synchronize(change);
70
        EventLogIndex::synchronize(change);
71
        switch (change) {
72
            case FileReader::UNCHANGED:   // just to avoid unused enumeration value warnings
73
                break;
74
            case FileReader::OVERWRITTEN:
75
                deleteAllocatedObjects();
76
                clearInternalState();
77
                parseKeyframes();
78
                break;
79
            case FileReader::APPENDED:
80
                for (EventNumberToEventMap::iterator it = eventNumberToEventMap.begin(); it != eventNumberToEventMap.end(); it++)
81
                    it->second->synchronize(change);
82
                if (lastEvent) {
83
                    IEvent::unlinkNeighbourEvents(lastEvent);
84
                    eventNumberToEventMap.erase(lastEvent->getEventNumber());
85
                    eventNumberToCacheEntryMap.erase(lastEvent->getEventNumber());
86
                    beginOffsetToEventMap.erase(lastEvent->getBeginOffset());
87
                    endOffsetToEventMap.erase(lastEvent->getEndOffset());
88
                    if (firstEvent == lastEvent) {
89
                        firstEvent = NULL;
90
                        simulationBeginEntry = NULL;
91
                    }
92
                    delete lastEvent;
93
                    lastEvent = NULL;
94
                }
95
                // TODO: we could do this incrementally
96
                parseKeyframes();
97
                break;
98
        }
99
    }
100
}
101

    
102
ProgressMonitor EventLog::setProgressMonitor(ProgressMonitor newProgressMonitor)
103
{
104
    ProgressMonitor oldProgressMonitor = progressMonitor;
105
    progressMonitor = newProgressMonitor;
106
    return oldProgressMonitor;
107
}
108

    
109
void EventLog::progress()
110
{
111
    if (lastProgressCall + progressCallInterval < (long)clock()) {
112
        progressMonitor.progress(this);
113
        lastProgressCall = clock();
114
    }
115
}
116

    
117
eventnumber_t EventLog::getApproximateNumberOfEvents()
118
{
119
    if (approximateNumberOfEvents == -1)
120
    {
121
        Event *firstEvent = getFirstEvent();
122
        Event *lastEvent = getLastEvent();
123

    
124
        if (firstEvent == NULL)
125
            approximateNumberOfEvents = 0;
126
        else
127
        {
128
            file_offset_t beginOffset = firstEvent->getBeginOffset();
129
            file_offset_t endOffset = lastEvent->getEndOffset();
130
            long sum = 0;
131
            long count = 0;
132
            int eventCount = 100;
133

    
134
            for (int i = 0; i < eventCount; i++)
135
            {
136
                if (firstEvent) {
137
                    sum += firstEvent->getEndOffset() - firstEvent->getBeginOffset();
138
                    count++;
139
                    firstEvent = firstEvent->getNextEvent();
140
                }
141

    
142
                if (lastEvent) {
143
                    sum += lastEvent->getEndOffset() - lastEvent->getBeginOffset();
144
                    count++;
145
                    lastEvent = lastEvent->getPreviousEvent();
146
                }
147
            }
148

    
149
            double average = (double)sum / count;
150
            approximateNumberOfEvents = (long)((endOffset - beginOffset) / average);
151
        }
152
    }
153

    
154
    return approximateNumberOfEvents;
155
}
156

    
157
Event *EventLog::getApproximateEventAt(double percentage)
158
{
159
    Event *firstEvent = getFirstEvent();
160
    Event *lastEvent = getLastEvent();
161

    
162
    if (firstEvent == NULL)
163
        return NULL;
164
    else {
165
        file_offset_t beginOffset = firstEvent->getBeginOffset();
166
        file_offset_t endOffset = lastEvent->getEndOffset();
167
        file_offset_t offset = beginOffset + (file_offset_t)((endOffset - beginOffset) * percentage);
168

    
169
        eventnumber_t eventNumber;
170
        file_offset_t lineStartOffset = -1, lineEndOffset;
171
        simtime_t simulationTime;
172
        readToEventLine(false, offset, eventNumber, simulationTime, lineStartOffset, lineEndOffset);
173

    
174
        Event *event = NULL;
175

    
176
        if (lineStartOffset == -1)
177
            event = getFirstEvent();
178
        else
179
            event = getEventForBeginOffset(lineStartOffset);
180

    
181
        Assert(event);
182

    
183
        return event;
184
    }
185
}
186

    
187
void EventLog::parseKeyframes()
188
{
189
    // NOTE: optimized for performance
190
    char *line;
191
    SimulationBeginEntry *simulationBeginEntry = getSimulationBeginEntry();
192
    if (simulationBeginEntry) {
193
        keyframeBlockSize = simulationBeginEntry->keyframeBlockSize;
194
        consequenceLookaheadLimits.resize(getLastEventNumber() / keyframeBlockSize + 1, 0);
195
        reader->seekTo(reader->getFileSize());
196
        while ((line = reader->getPreviousLineBufferPointer())) {
197
            EventLogEntry *eventLogEntry = (EventLogEntry *)EventLogEntry::parseEntry(this, NULL, 0, reader->getCurrentLineStartOffset(), line, reader->getCurrentLineLength());
198
            if (dynamic_cast<KeyframeEntry *>(eventLogEntry)) {
199
                KeyframeEntry *keyframeEntry = (KeyframeEntry *)eventLogEntry;
200
                // store consequenceLookaheadLimits from the keyframe
201
                char *s = const_cast<char *>(keyframeEntry->consequenceLookaheadLimits);
202
                while (*s != '\0') {
203
                    eventnumber_t eventNumber = strtol(s, &s, 10);
204
                    eventnumber_t keyframeIndex = eventNumber / keyframeBlockSize;
205
                    s++;
206
                    eventnumber_t consequenceLookaheadLimit = strtol(s, &s, 10);
207
                    s++;
208
                    consequenceLookaheadLimits[keyframeIndex] = std::max(consequenceLookaheadLimits[keyframeIndex], consequenceLookaheadLimit);
209
                }
210
                // TODO: store simulation state data from the keyframe
211
                // jump to previous keyframe
212
                reader->seekTo(keyframeEntry->previousKeyframeFileOffset + 1);
213
                reader->getNextLineBufferPointer();
214
            }
215
            else if (dynamic_cast<MessageEntry *>(eventLogEntry)) {
216
                MessageEntry *messageEntry = (MessageEntry *)eventLogEntry;
217
                if (messageEntry->previousEventNumber != -1) {
218
                    int blockIndex = messageEntry->previousEventNumber / keyframeBlockSize;
219
                    // NOTE: the last event number is a reasonable approximation here
220
                    consequenceLookaheadLimits[blockIndex] = std::max(consequenceLookaheadLimits[blockIndex], getLastEventNumber() - messageEntry->previousEventNumber);
221
                }
222
            }
223
            delete eventLogEntry;
224
            progress();
225
        }
226
    }
227
}
228

    
229
std::vector<ModuleCreatedEntry *> EventLog::getModuleCreatedEntries()
230
{
231
    std::vector<ModuleCreatedEntry *> moduleCreatedEntries;
232

    
233
    for (ModuleIdToModuleCreatedEntryMap::iterator it = moduleIdToModuleCreatedEntryMap.begin(); it != moduleIdToModuleCreatedEntryMap.end(); it++) {
234
        Assert(it->second);
235
        moduleCreatedEntries.push_back(it->second);
236
    }
237

    
238
    return moduleCreatedEntries;
239
}
240

    
241
ModuleCreatedEntry *EventLog::getModuleCreatedEntry(int moduleId)
242
{
243
    ModuleIdToModuleCreatedEntryMap::iterator it = moduleIdToModuleCreatedEntryMap.find(moduleId);
244

    
245
    if (it == moduleIdToModuleCreatedEntryMap.end())
246
        return NULL;
247
    else
248
        return it->second;
249
}
250

    
251
GateCreatedEntry *EventLog::getGateCreatedEntry(int moduleId, int gateId)
252
{
253
    std::pair<int, int> key(moduleId, gateId);
254
    ModuleIdAndGateIdToGateCreatedEntryMap::iterator it = moduleIdAndGateIdToGateCreatedEntryMap.find(key);
255

    
256
    if (it == moduleIdAndGateIdToGateCreatedEntryMap.end())
257
        return NULL;
258
    else
259
        return it->second;
260
}
261

    
262
Event *EventLog::getFirstEvent()
263
{
264
    if (!firstEvent) {
265
        file_offset_t offset = getFirstEventOffset();
266

    
267
        if (offset != -1)
268
            firstEvent = getEventForBeginOffset(offset);
269
    }
270

    
271
    return firstEvent;
272
}
273

    
274
Event *EventLog::getLastEvent()
275
{
276
    if (!lastEvent) {
277
        file_offset_t offset = getLastEventOffset();
278

    
279
        if (offset != -1)
280
            lastEvent = getEventForBeginOffset(offset);
281
    }
282

    
283
    return lastEvent;
284
}
285

    
286
Event *EventLog::getEventForEventNumber(eventnumber_t eventNumber, MatchKind matchKind, bool useCacheOnly)
287
{
288
    Assert(eventNumber >= 0);
289
    if (matchKind == EXACT) {
290
        EventNumberToEventMap::iterator it = eventNumberToEventMap.find(eventNumber);
291
        if (it != eventNumberToEventMap.end())
292
            return it->second;
293
        else if (useCacheOnly)
294
            return NULL;
295
        else {
296
            // the following two are still faster than binary searching
297
            // but this may access the disk
298
            it = eventNumberToEventMap.find(eventNumber - 1);
299
            if (it != eventNumberToEventMap.end())
300
                return it->second->getNextEvent();
301

    
302
            it = eventNumberToEventMap.find(eventNumber + 1);
303
            if (it != eventNumberToEventMap.end())
304
                return it->second->getPreviousEvent();
305
        }
306
    }
307
    if (useCacheOnly)
308
        return NULL;
309
    else {
310
        // TODO: shall we cache result
311
        file_offset_t offset = getOffsetForEventNumber(eventNumber, matchKind);
312
        if (offset == -1)
313
            return NULL;
314
        else
315
            return getEventForBeginOffset(offset);
316
    }
317
}
318

    
319
Event *EventLog::getNeighbourEvent(IEvent *event, eventnumber_t distance)
320
{
321
    Assert(event);
322
    return (Event *)IEventLog::getNeighbourEvent(event, distance);
323
}
324

    
325
Event *EventLog::getEventForSimulationTime(simtime_t simulationTime, MatchKind matchKind, bool useCacheOnly)
326
{
327
    if (useCacheOnly)
328
        return NULL;
329
    else {
330
        Assert(simulationTime >= 0);
331
        file_offset_t offset = getOffsetForSimulationTime(simulationTime, matchKind);
332

    
333
        if (offset == -1)
334
            return NULL;
335
        else
336
            return getEventForBeginOffset(offset);
337
    }
338
}
339

    
340
EventLogEntry *EventLog::findEventLogEntry(EventLogEntry *start, const char *search, bool forward, bool caseSensitive)
341
{
342
    char *line;
343
    reader->seekTo(start->getEvent()->getBeginOffset());
344
    int index = start->getEntryIndex();
345

    
346
    for (int i = 0; i < index + forward ? 1 : 0; i++)
347
        reader->getNextLineBufferPointer();
348

    
349
    if (forward)
350
        line = reader->findNextLineBufferPointer(search, caseSensitive);
351
    else
352
        line = reader->findPreviousLineBufferPointer(search, caseSensitive);
353

    
354
    if (line) {
355
        if (forward)
356
            line = reader->getPreviousLineBufferPointer();
357

    
358
        index = 0;
359

    
360
        do {
361
            if (line[0] == 'E' && line[1] == ' ')
362
                return getEventForBeginOffset(reader->getCurrentLineStartOffset())->getEventLogEntry(index);
363
            else if (line[0] != '\r' && line[0] != '\n')
364
                index++;
365
        }
366
        while ((line = reader->getPreviousLineBufferPointer()));
367
    }
368

    
369
    return NULL;
370
}
371

    
372
Event *EventLog::getEventForBeginOffset(file_offset_t beginOffset)
373
{
374
    Assert(beginOffset >= 0);
375
    OffsetToEventMap::iterator it = beginOffsetToEventMap.find(beginOffset);
376

    
377
    if (it != beginOffsetToEventMap.end())
378
        return it->second;
379
    else if (reader->getFileSize() != beginOffset)
380
    {
381
        Event *event = new Event(this);
382
        parseEvent(event, beginOffset);
383
        cacheEvent(event);
384
        return event;
385
    }
386
    else {
387
        beginOffsetToEventMap[beginOffset] = NULL;
388
        return NULL;
389
    }
390
}
391

    
392
Event *EventLog::getEventForEndOffset(file_offset_t endOffset)
393
{
394
    Assert(endOffset >= 0);
395
    OffsetToEventMap::iterator it = endOffsetToEventMap.find(endOffset);
396

    
397
    if (it != endOffsetToEventMap.end())
398
        return it->second;
399
    else {
400
        file_offset_t beginOffset = getBeginOffsetForEndOffset(endOffset);
401

    
402
        if (beginOffset == -1) {
403
            endOffsetToEventMap[endOffset] = NULL;
404
            return NULL;
405
        }
406
        else
407
            return getEventForBeginOffset(beginOffset);
408
    }
409
}
410

    
411
void EventLog::parseEvent(Event *event, file_offset_t beginOffset)
412
{
413
    event->parse(reader, beginOffset);
414
    cacheEntry(event->getEventNumber(), event->getSimulationTime(), event->getBeginOffset(), event->getEndOffset());
415
    cacheEventLogEntries(event);
416
    numParsedEvents++;
417
    Assert(event->getEventEntry());
418
}
419

    
420
void EventLog::cacheEventLogEntries(Event *event)
421
{
422
    for (int i = 0; i < event->getNumEventLogEntries(); i++)
423
        cacheEventLogEntry(event->getEventLogEntry(i));
424
}
425

    
426
void EventLog::uncacheEventLogEntries(Event *event)
427
{
428
    for (int i = 0; i < event->getNumEventLogEntries(); i++)
429
        uncacheEventLogEntry(event->getEventLogEntry(i));
430
}
431

    
432
void EventLog::cacheEventLogEntry(EventLogEntry *eventLogEntry)
433
{
434
    // simulation begin entry
435
    SimulationBeginEntry *simulationBeginEntry = dynamic_cast<SimulationBeginEntry *>(eventLogEntry);
436

    
437
    if (simulationBeginEntry)
438
        this->simulationBeginEntry = simulationBeginEntry;
439

    
440
    // simulation begin entry
441
    SimulationEndEntry *simulationEndEntry = dynamic_cast<SimulationEndEntry *>(eventLogEntry);
442

    
443
    if (simulationEndEntry)
444
        this->simulationEndEntry = simulationEndEntry;
445

    
446
    // collect module created entries
447
    ModuleCreatedEntry *moduleCreatedEntry = dynamic_cast<ModuleCreatedEntry *>(eventLogEntry);
448

    
449
    if (moduleCreatedEntry)
450
        moduleIdToModuleCreatedEntryMap[moduleCreatedEntry->moduleId] = moduleCreatedEntry;
451

    
452
    // collect gate created entries
453
    GateCreatedEntry *gateCreatedEntry = dynamic_cast<GateCreatedEntry *>(eventLogEntry);
454

    
455
    if (gateCreatedEntry) {
456
        std::pair<int, int> key(gateCreatedEntry->moduleId, gateCreatedEntry->gateId);
457
        moduleIdAndGateIdToGateCreatedEntryMap[key] = gateCreatedEntry;
458
    }
459

    
460
    // colllect begin send entry
461
    BeginSendEntry *beginSendEntry = dynamic_cast<BeginSendEntry *>(eventLogEntry);
462
    if (beginSendEntry) {
463
        messageNames.insert(beginSendEntry->messageName);
464
        messageClassNames.insert(beginSendEntry->messageClassName);
465
    }
466
}
467

    
468
void EventLog::uncacheEventLogEntry(EventLogEntry *eventLogEntry)
469
{
470
    // collect module created entries
471
//    ModuleCreatedEntry *moduleCreatedEntry = dynamic_cast<ModuleCreatedEntry *>(eventLogEntry);
472
//    if (moduleCreatedEntry)
473
//        moduleIdToModuleCreatedEntryMap.erase(moduleCreatedEntry->moduleId);
474

    
475
    // collect gate created entries
476
    GateCreatedEntry *gateCreatedEntry = dynamic_cast<GateCreatedEntry *>(eventLogEntry);
477

    
478
    if (gateCreatedEntry) {
479
        std::pair<int, int> key(gateCreatedEntry->moduleId, gateCreatedEntry->gateId);
480
        moduleIdAndGateIdToGateCreatedEntryMap.erase(key);
481
    }
482
}
483

    
484
void EventLog::cacheEvent(Event *event)
485
{
486
    int eventNumber = event->getEventNumber();
487
    Assert(!lastEvent || eventNumber <= lastEvent->getEventNumber());
488
    Assert(eventNumberToEventMap.find(eventNumber) == eventNumberToEventMap.end());
489

    
490
    eventNumberToEventMap[eventNumber] = event;
491
    beginOffsetToEventMap[event->getBeginOffset()] = event;
492
    endOffsetToEventMap[event->getEndOffset()] = event;
493
}
494

    
495
std::vector<MessageEntry *> EventLog::getMessageEntriesWithPreviousEventNumber(eventnumber_t previousEventNumber)
496
{
497
    std::map<eventnumber_t, std::vector<MessageEntry *> >::iterator it = previousEventNumberToMessageEntriesMap.find(previousEventNumber);
498
    if (it != previousEventNumberToMessageEntriesMap.end())
499
        return it->second;
500
    else {
501
        eventnumber_t keyframeBlockIndex = previousEventNumber / keyframeBlockSize;
502
        eventnumber_t beginEventNumber = (eventnumber_t)keyframeBlockIndex * keyframeBlockSize;
503
        eventnumber_t endEventNumber = beginEventNumber + keyframeBlockSize;
504
        eventnumber_t consequenceLookahead = getConsequenceLookahead(previousEventNumber);
505
        for (eventnumber_t i = beginEventNumber; i < endEventNumber; i++)
506
            previousEventNumberToMessageEntriesMap[i] = std::vector<MessageEntry *>();
507
        eventnumber_t eventNumber = beginEventNumber;
508
        Event *event = getEventForEventNumber(beginEventNumber);
509
        while (eventNumber < endEventNumber + consequenceLookahead) {
510
            if (event) {
511
                for (int i = 0; i < (int)event->getNumEventLogEntries(); i++) {
512
                    MessageEntry *messageEntry = dynamic_cast<MessageEntry *>(event->getEventLogEntry(i));
513
                    if (messageEntry) {
514
                        eventnumber_t messageEntryPreviousEventNumber =  messageEntry->previousEventNumber;
515
                        if (beginEventNumber <= messageEntryPreviousEventNumber && messageEntryPreviousEventNumber < endEventNumber && messageEntryPreviousEventNumber != event->getEventNumber()) {
516
                            it = previousEventNumberToMessageEntriesMap.find(messageEntryPreviousEventNumber);
517
                            it->second.push_back(messageEntry);
518
                        }
519
                    }
520
                }
521
                eventNumber++;
522
                event = event->getNextEvent();
523
            }
524
            else {
525
                eventNumber++;
526
                event = getEventForEventNumber(beginEventNumber);
527
            }
528
        }
529
        return previousEventNumberToMessageEntriesMap.find(previousEventNumber)->second;
530
    }
531
}
532

    
533
NAMESPACE_END