Statistics
| Branch: | Revision:

root / src / eventlog / eventlog.cc @ 81ad8b66

History | View | Annotate | Download (14.1 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::getEventForEventNumber(eventnumber_t eventNumber, MatchKind matchKind)
290
{
291
    Assert(eventNumber >= 0);
292

    
293
    if (matchKind == EXACT) {
294
        EventNumberToEventMap::iterator it = eventNumberToEventMap.find(eventNumber);
295
        if (it != eventNumberToEventMap.end())
296
            return it->second;
297

    
298
        // the following two are still faster than binary searching
299
        it = eventNumberToEventMap.find(eventNumber - 1);
300
        if (it != eventNumberToEventMap.end())
301
            return it->second->getNextEvent();
302

    
303
        it = eventNumberToEventMap.find(eventNumber + 1);
304
        if (it != eventNumberToEventMap.end())
305
            return it->second->getPreviousEvent();
306
    }
307

    
308
    // TODO: maybe cache result
309
    file_offset_t offset = getOffsetForEventNumber(eventNumber, matchKind);
310

    
311
    if (offset == -1)
312
        return NULL;
313
    else
314
        return getEventForBeginOffset(offset);
315
}
316

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

    
323
Event *EventLog::getEventForSimulationTime(simtime_t simulationTime, MatchKind matchKind)
324
{
325
    Assert(simulationTime >= 0);
326

    
327
    file_offset_t offset = getOffsetForSimulationTime(simulationTime, matchKind);
328

    
329
    if (offset == -1)
330
        return NULL;
331
    else
332
        return getEventForBeginOffset(offset);
333
}
334

    
335
EventLogEntry *EventLog::findEventLogEntry(EventLogEntry *start, const char *search, bool forward, bool caseSensitive)
336
{
337
    char *line;
338
    reader->seekTo(start->getEvent()->getBeginOffset());
339
    int index = start->getEntryIndex();
340

    
341
    for (int i = 0; i < index + forward ? 1 : 0; i++)
342
        reader->getNextLineBufferPointer();
343

    
344
    if (forward)
345
        line = reader->findNextLineBufferPointer(search, caseSensitive);
346
    else
347
        line = reader->findPreviousLineBufferPointer(search, caseSensitive);
348

    
349
    if (line) {
350
        if (forward)
351
            line = reader->getPreviousLineBufferPointer();
352

    
353
        index = 0;
354

    
355
        do {
356
            if (line[0] == 'E' && line[1] == ' ')
357
                return getEventForBeginOffset(reader->getCurrentLineStartOffset())->getEventLogEntry(index);
358
            else if (line[0] != '\r' && line[0] != '\n')
359
                index++;
360
        }
361
        while ((line = reader->getPreviousLineBufferPointer()));
362
    }
363

    
364
    return NULL;
365
}
366

    
367
Event *EventLog::getEventForBeginOffset(file_offset_t beginOffset)
368
{
369
    Assert(beginOffset >= 0);
370
    OffsetToEventMap::iterator it = beginOffsetToEventMap.find(beginOffset);
371

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

    
387
Event *EventLog::getEventForEndOffset(file_offset_t endOffset)
388
{
389
    Assert(endOffset >= 0);
390
    OffsetToEventMap::iterator it = endOffsetToEventMap.find(endOffset);
391

    
392
    if (it != endOffsetToEventMap.end())
393
        return it->second;
394
    else {
395
        file_offset_t beginOffset = getBeginOffsetForEndOffset(endOffset);
396

    
397
        if (beginOffset == -1) {
398
            endOffsetToEventMap[endOffset] = NULL;
399
            return NULL;
400
        }
401
        else
402
            return getEventForBeginOffset(beginOffset);
403
    }
404
}
405

    
406
void EventLog::parseEvent(Event *event, file_offset_t beginOffset)
407
{
408
    event->parse(reader, beginOffset);
409
    if(event->getEventEndEntry() != NULL)
410
        legacyTrace = false;
411

    
412
    cacheEntry(event->getEventNumber(), event->getSimulationTime(), event->getBeginOffset(), event->getEndOffset());
413
    cacheEventLogEntries(event);
414
    numParsedEvents++;
415
}
416

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

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

    
429
void EventLog::cacheEventLogEntry(EventLogEntry *eventLogEntry)
430
{
431
    // simulation begin entry
432
    SimulationBeginEntry *simulationBeginEntry = dynamic_cast<SimulationBeginEntry *>(eventLogEntry);
433

    
434
    if (simulationBeginEntry)
435
        this->simulationBeginEntry = simulationBeginEntry;
436

    
437
    // collect module created entries
438
    ModuleCreatedEntry *moduleCreatedEntry = dynamic_cast<ModuleCreatedEntry *>(eventLogEntry);
439

    
440
    if (moduleCreatedEntry) {
441
        moduleIdToModuleCreatedEntryMap[moduleCreatedEntry->moduleId] = moduleCreatedEntry;
442
        getModuleCreatedEntries();
443
    }
444

    
445
    // collect gate created entries
446
    GateCreatedEntry *gateCreatedEntry = dynamic_cast<GateCreatedEntry *>(eventLogEntry);
447

    
448
    if (gateCreatedEntry) {
449
        std::pair<int, int> key(gateCreatedEntry->moduleId, gateCreatedEntry->gateId);
450
        moduleIdAndGateIdToGateCreatedEntryMap[key] = gateCreatedEntry;
451
    }
452

    
453
    // colllect begin send entry
454
    BeginSendEntry *beginSendEntry = dynamic_cast<BeginSendEntry *>(eventLogEntry);
455
    if (beginSendEntry) {
456
        messageNames.insert(beginSendEntry->messageFullName);
457
        messageClassNames.insert(beginSendEntry->messageClassName);
458
    }
459
}
460

    
461
void EventLog::uncacheEventLogEntry(EventLogEntry *eventLogEntry)
462
{
463
    // collect module created entries
464
//    ModuleCreatedEntry *moduleCreatedEntry = dynamic_cast<ModuleCreatedEntry *>(eventLogEntry);
465
//    if (moduleCreatedEntry)
466
//        moduleIdToModuleCreatedEntryMap.erase(moduleCreatedEntry->moduleId);
467

    
468
    // collect gate created entries
469
    GateCreatedEntry *gateCreatedEntry = dynamic_cast<GateCreatedEntry *>(eventLogEntry);
470

    
471
    if (gateCreatedEntry) {
472
        std::pair<int, int> key(gateCreatedEntry->moduleId, gateCreatedEntry->gateId);
473
        moduleIdAndGateIdToGateCreatedEntryMap.erase(key);
474
    }
475
}
476

    
477
void EventLog::cacheEvent(Event *event)
478
{
479
    int eventNumber = event->getEventNumber();
480
    Assert(!lastEvent || eventNumber <= lastEvent->getEventNumber());
481
    Assert(eventNumberToEventMap.find(eventNumber) == eventNumberToEventMap.end());
482

    
483
    eventNumberToEventMap[eventNumber] = event;
484
    beginOffsetToEventMap[event->getBeginOffset()] = event;
485
    endOffsetToEventMap[event->getEndOffset()] = event;
486
}
487

    
488
NAMESPACE_END