Statistics
| Branch: | Revision:

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

History | View | Annotate | Download (14.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->setSynchronizeWhenAppended(false);
29

    
30
    clearInternalState();
31
    parseInitializationLogEntries();
32
}
33

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

    
39
void EventLog::deleteAllocatedObjects()
40
{
41
    for (EventLogEntryList::iterator it = initializationLogEntries.begin(); it != initializationLogEntries.end(); it++)
42
        delete *it;
43

    
44
    for (EventNumberToEventMap::iterator it = eventNumberToEventMap.begin(); it != eventNumberToEventMap.end(); it++)
45
        delete it->second;
46

    
47
    clearInternalState();
48
}
49

    
50
void EventLog::clearInternalState(FileReader::FileChangedState change)
51
{
52
    Assert(change != FileReader::UNCHANGED);
53
    approximateNumberOfEvents = -1;
54

    
55
    // lastEvent should be set to null if the last event becomes a different one
56
    if (change == FileReader::OVERWRITTEN) {
57
        numParsedEvents = 0;
58

    
59
        progressCallInterval = CLOCKS_PER_SEC;
60
        lastProgressCall = -1;
61

    
62
        firstEvent = NULL;
63
        lastEvent = NULL;
64

    
65
        legacyTrace = true;
66

    
67
        messageNames.clear();
68
        messageClassNames.clear();
69

    
70
        initializationLogEntries.clear();
71
//        moduleIdToModuleCreatedEntryMap.clear();
72
        moduleIdAndGateIdToGateCreatedEntryMap.clear();
73

    
74
        simulationBeginEntry = NULL;
75

    
76
        eventNumberToEventMap.clear();
77
        beginOffsetToEventMap.clear();
78
        endOffsetToEventMap.clear();
79
    }
80
    else if (lastEvent && lastEvent->getBeginOffset() != getLastEventOffset())
81
        lastEvent = NULL;
82
}
83

    
84
void EventLog::synchronize(FileReader::FileChangedState change)
85
{
86
    if (change != FileReader::UNCHANGED) {
87
        if (change == FileReader::OVERWRITTEN)
88
            deleteAllocatedObjects();
89

    
90
        Event *lastEvent = this->lastEvent;
91

    
92
        IEventLog::synchronize(change);
93
        EventLogIndex::synchronize(change);
94

    
95
        if (change == FileReader::APPENDED) {
96
            clearInternalState(change);
97

    
98
            // always update the old last event because it might have been incomplete
99
            if (lastEvent)
100
                parseEvent(lastEvent, lastEvent->getBeginOffset());
101

    
102
            for (EventNumberToEventMap::iterator it = eventNumberToEventMap.begin(); it != eventNumberToEventMap.end(); it++)
103
                it->second->synchronize();
104
        }
105
        else
106
            parseInitializationLogEntries();
107
    }
108
}
109

    
110
ProgressMonitor EventLog::setProgressMonitor(ProgressMonitor newProgressMonitor)
111
{
112
    ProgressMonitor oldProgressMonitor = progressMonitor;
113
    progressMonitor = newProgressMonitor;
114
    return oldProgressMonitor;
115
}
116

    
117
void EventLog::progress()
118
{
119
    if (lastProgressCall + progressCallInterval < clock()) {
120
        progressMonitor.progress(this);
121
        lastProgressCall = clock();
122
    }
123
}
124

    
125
eventnumber_t EventLog::getApproximateNumberOfEvents()
126
{
127
    if (approximateNumberOfEvents == -1)
128
    {
129
        Event *firstEvent = getFirstEvent();
130
        Event *lastEvent = getLastEvent();
131

    
132
        if (firstEvent == NULL)
133
            approximateNumberOfEvents = 0;
134
        else
135
        {
136
            file_offset_t beginOffset = firstEvent->getBeginOffset();
137
            file_offset_t endOffset = lastEvent->getEndOffset();
138
            long sum = 0;
139
            long count = 0;
140
            int eventCount = 100;
141

    
142
            for (int i = 0; i < eventCount; i++)
143
            {
144
                if (firstEvent) {
145
                    sum += firstEvent->getEndOffset() - firstEvent->getBeginOffset();
146
                    count++;
147
                    firstEvent = firstEvent->getNextEvent();
148
                }
149

    
150
                if (lastEvent) {
151
                    sum += lastEvent->getEndOffset() - lastEvent->getBeginOffset();
152
                    count++;
153
                    lastEvent = lastEvent->getPreviousEvent();
154
                }
155
            }
156

    
157
            double average = (double)sum / count;
158
            approximateNumberOfEvents = (long)((endOffset - beginOffset) / average);
159
        }
160
    }
161

    
162
    return approximateNumberOfEvents;
163
}
164

    
165
Event *EventLog::getApproximateEventAt(double percentage)
166
{
167
    Event *firstEvent = getFirstEvent();
168
    Event *lastEvent = getLastEvent();
169

    
170
    if (firstEvent == NULL)
171
        return NULL;
172
    else {
173
        file_offset_t beginOffset = firstEvent->getBeginOffset();
174
        file_offset_t endOffset = lastEvent->getEndOffset();
175
        file_offset_t offset = beginOffset + (file_offset_t)((endOffset - beginOffset) * percentage);
176

    
177
        eventnumber_t eventNumber;
178
        file_offset_t lineStartOffset = -1, lineEndOffset;
179
        simtime_t simulationTime;
180
        readToEventLine(false, offset, eventNumber, simulationTime, lineStartOffset, lineEndOffset);
181

    
182
        Event *event = NULL;
183

    
184
        if (lineStartOffset == -1)
185
            event = getFirstEvent();
186
        else
187
            event = getEventForBeginOffset(lineStartOffset);
188

    
189
        Assert(event);
190

    
191
        return event;
192
    }
193
}
194

    
195
void EventLog::parseInitializationLogEntries()
196
{
197
    int index = 0;
198
    reader->seekTo(0);
199

    
200
    if (PRINT_DEBUG_MESSAGES) printf("Parsing initialization log entries at: 0\n");
201

    
202
    while (true)
203
    {
204
        char *line = reader->getNextLineBufferPointer();
205

    
206
        if (!line)
207
            break;
208

    
209
        EventLogEntry *eventLogEntry = EventLogEntry::parseEntry(NULL, index, line, reader->getCurrentLineLength());
210

    
211
        if (!eventLogEntry)
212
            continue;
213
        else
214
            index++;
215

    
216
        if (dynamic_cast<EventEntry *>(eventLogEntry)) {
217
            delete eventLogEntry;
218
            break;
219
        }
220

    
221
        initializationLogEntries.push_back(eventLogEntry);
222
        cacheEventLogEntry(eventLogEntry);
223
    }
224
}
225

    
226
void EventLog::printInitializationLogEntries(FILE *file)
227
{
228
    for (EventLogEntryList::iterator it = initializationLogEntries.begin(); it != initializationLogEntries.end(); it++)
229
        (*it)->print(file);
230
}
231

    
232
std::vector<ModuleCreatedEntry *> EventLog::getModuleCreatedEntries()
233
{
234
    std::vector<ModuleCreatedEntry *> moduleCreatedEntries;
235

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

    
241
    return moduleCreatedEntries;
242
}
243

    
244
ModuleCreatedEntry *EventLog::getModuleCreatedEntry(int moduleId)
245
{
246
    ModuleIdToModuleCreatedEntryMap::iterator it = moduleIdToModuleCreatedEntryMap.find(moduleId);
247

    
248
    if (it == moduleIdToModuleCreatedEntryMap.end())
249
        return NULL;
250
    else
251
        return it->second;
252
}
253

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

    
259
    if (it == moduleIdAndGateIdToGateCreatedEntryMap.end())
260
        return NULL;
261
    else
262
        return it->second;
263
}
264

    
265
Event *EventLog::getFirstEvent()
266
{
267
    if (!firstEvent) {
268
        file_offset_t offset = getFirstEventOffset();
269

    
270
        if (offset != -1)
271
            firstEvent = getEventForBeginOffset(offset);
272
    }
273

    
274
    return firstEvent;
275
}
276

    
277
Event *EventLog::getLastEvent()
278
{
279
    if (!lastEvent) {
280
        file_offset_t offset = getLastEventOffset();
281

    
282
        if (offset != -1)
283
            lastEvent = getEventForBeginOffset(offset);
284
    }
285

    
286
    return lastEvent;
287
}
288

    
289
Event *EventLog::getFirstEventRealTime()
290
{
291
    Assert(firstEventRealTime != NULL);
292
    return firstEventRealTime;
293
}
294

    
295
Event *EventLog::getLastEventRealTime()
296
{
297
    Assert(lastEventRealTime != NULL);
298
    return lastEventRealTime;
299
}
300

    
301
Event *EventLog::getEventForEventNumber(eventnumber_t eventNumber, MatchKind matchKind)
302
{
303
    Assert(eventNumber >= 0);
304

    
305
    if (matchKind == EXACT) {
306
        EventNumberToEventMap::iterator it = eventNumberToEventMap.find(eventNumber);
307
        if (it != eventNumberToEventMap.end())
308
            return it->second;
309

    
310
        // the following two are still faster than binary searching
311
        it = eventNumberToEventMap.find(eventNumber - 1);
312
        if (it != eventNumberToEventMap.end())
313
            return it->second->getNextEvent();
314

    
315
        it = eventNumberToEventMap.find(eventNumber + 1);
316
        if (it != eventNumberToEventMap.end())
317
            return it->second->getPreviousEvent();
318
    }
319

    
320
    // TODO: maybe cache result
321
    file_offset_t offset = getOffsetForEventNumber(eventNumber, matchKind);
322

    
323
    if (offset == -1)
324
        return NULL;
325
    else
326
        return getEventForBeginOffset(offset);
327
}
328

    
329
Event *EventLog::getNeighbourEvent(IEvent *event, eventnumber_t distance)
330
{
331
    Assert(event);
332
    return (Event *)IEventLog::getNeighbourEvent(event, distance);
333
}
334

    
335
Event *EventLog::getEventForSimulationTime(simtime_t simulationTime, MatchKind matchKind)
336
{
337
    Assert(simulationTime >= 0);
338

    
339
    file_offset_t offset = getOffsetForSimulationTime(simulationTime, matchKind);
340

    
341
    if (offset == -1)
342
        return NULL;
343
    else
344
        return getEventForBeginOffset(offset);
345
}
346

    
347
EventLogEntry *EventLog::findEventLogEntry(EventLogEntry *start, const char *search, bool forward, bool caseSensitive)
348
{
349
    char *line;
350
    reader->seekTo(start->getEvent()->getBeginOffset());
351
    int index = start->getEntryIndex();
352

    
353
    for (int i = 0; i < index + forward ? 1 : 0; i++)
354
        reader->getNextLineBufferPointer();
355

    
356
    if (forward)
357
        line = reader->findNextLineBufferPointer(search, caseSensitive);
358
    else
359
        line = reader->findPreviousLineBufferPointer(search, caseSensitive);
360

    
361
    if (line) {
362
        if (forward)
363
            line = reader->getPreviousLineBufferPointer();
364

    
365
        index = 0;
366

    
367
        do {
368
            if (line[0] == 'E' && line[1] == ' ')
369
                return getEventForBeginOffset(reader->getCurrentLineStartOffset())->getEventLogEntry(index);
370
            else if (line[0] != '\r' && line[0] != '\n')
371
                index++;
372
        }
373
        while ((line = reader->getPreviousLineBufferPointer()));
374
    }
375

    
376
    return NULL;
377
}
378

    
379
Event *EventLog::getEventForBeginOffset(file_offset_t beginOffset)
380
{
381
    Assert(beginOffset >= 0);
382
    OffsetToEventMap::iterator it = beginOffsetToEventMap.find(beginOffset);
383

    
384
    if (it != beginOffsetToEventMap.end())
385
        return it->second;
386
    else if (reader->getFileSize() != beginOffset)
387
    {
388
        Event *event = new Event(this);
389
        parseEvent(event, beginOffset);
390
        cacheEvent(event);
391
        return event;
392
    }
393
    else {
394
        beginOffsetToEventMap[beginOffset] = NULL;
395
        return NULL;
396
    }
397
}
398

    
399
Event *EventLog::getEventForEndOffset(file_offset_t endOffset)
400
{
401
    Assert(endOffset >= 0);
402
    OffsetToEventMap::iterator it = endOffsetToEventMap.find(endOffset);
403

    
404
    if (it != endOffsetToEventMap.end())
405
        return it->second;
406
    else {
407
        file_offset_t beginOffset = getBeginOffsetForEndOffset(endOffset);
408

    
409
        if (beginOffset == -1) {
410
            endOffsetToEventMap[endOffset] = NULL;
411
            return NULL;
412
        }
413
        else
414
            return getEventForBeginOffset(beginOffset);
415
    }
416
}
417

    
418
void EventLog::parseEvent(Event *event, file_offset_t beginOffset)
419
{
420
    event->parse(reader, beginOffset);
421
    if(event->getEventEndEntry() != NULL)
422
        legacyTrace = false;
423

    
424
    cacheEntry(event->getEventNumber(), event->getSimulationTime(), event->getBeginOffset(), event->getEndOffset());
425
    cacheEventLogEntries(event);
426
    numParsedEvents++;
427
}
428

    
429
void EventLog::cacheEventLogEntries(Event *event)
430
{
431
    for (int i = 0; i < event->getNumEventLogEntries(); i++)
432
        cacheEventLogEntry(event->getEventLogEntry(i));
433
}
434

    
435
void EventLog::uncacheEventLogEntries(Event *event)
436
{
437
    for (int i = 0; i < event->getNumEventLogEntries(); i++)
438
        uncacheEventLogEntry(event->getEventLogEntry(i));
439
}
440

    
441
void EventLog::cacheEventLogEntry(EventLogEntry *eventLogEntry)
442
{
443
    // simulation begin entry
444
    SimulationBeginEntry *simulationBeginEntry = dynamic_cast<SimulationBeginEntry *>(eventLogEntry);
445

    
446
    if (simulationBeginEntry)
447
        this->simulationBeginEntry = simulationBeginEntry;
448

    
449
    // collect module created entries
450
    ModuleCreatedEntry *moduleCreatedEntry = dynamic_cast<ModuleCreatedEntry *>(eventLogEntry);
451

    
452
    if (moduleCreatedEntry) {
453
        moduleIdToModuleCreatedEntryMap[moduleCreatedEntry->moduleId] = moduleCreatedEntry;
454
        getModuleCreatedEntries();
455
    }
456

    
457
    // collect gate created entries
458
    GateCreatedEntry *gateCreatedEntry = dynamic_cast<GateCreatedEntry *>(eventLogEntry);
459

    
460
    if (gateCreatedEntry) {
461
        std::pair<int, int> key(gateCreatedEntry->moduleId, gateCreatedEntry->gateId);
462
        moduleIdAndGateIdToGateCreatedEntryMap[key] = gateCreatedEntry;
463
    }
464

    
465
    // colllect begin send entry
466
    BeginSendEntry *beginSendEntry = dynamic_cast<BeginSendEntry *>(eventLogEntry);
467
    if (beginSendEntry) {
468
        messageNames.insert(beginSendEntry->messageFullName);
469
        messageClassNames.insert(beginSendEntry->messageClassName);
470
    }
471
}
472

    
473
void EventLog::uncacheEventLogEntry(EventLogEntry *eventLogEntry)
474
{
475
    // collect module created entries
476
//    ModuleCreatedEntry *moduleCreatedEntry = dynamic_cast<ModuleCreatedEntry *>(eventLogEntry);
477
//    if (moduleCreatedEntry)
478
//        moduleIdToModuleCreatedEntryMap.erase(moduleCreatedEntry->moduleId);
479

    
480
    // collect gate created entries
481
    GateCreatedEntry *gateCreatedEntry = dynamic_cast<GateCreatedEntry *>(eventLogEntry);
482

    
483
    if (gateCreatedEntry) {
484
        std::pair<int, int> key(gateCreatedEntry->moduleId, gateCreatedEntry->gateId);
485
        moduleIdAndGateIdToGateCreatedEntryMap.erase(key);
486
    }
487
}
488

    
489
void EventLog::cacheEvent(Event *event)
490
{
491
    int eventNumber = event->getEventNumber();
492
    Assert(!lastEvent || eventNumber <= lastEvent->getEventNumber());
493
    Assert(eventNumberToEventMap.find(eventNumber) == eventNumberToEventMap.end());
494

    
495
    eventNumberToEventMap[eventNumber] = event;
496
    beginOffsetToEventMap[event->getBeginOffset()] = event;
497
    endOffsetToEventMap[event->getEndOffset()] = event;
498
}
499

    
500
NAMESPACE_END