Statistics
| Branch: | Revision:

root / src / eventlog / eventlogtablefacade.cc @ e1750c09

History | View | Annotate | Download (11.7 KB)

1 01873262 Georg Kunz
//=========================================================================
2
//  EVENTLOGTABLEFACADE.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 "ievent.h"
19
#include "ieventlog.h"
20
#include "event.h"
21
#include "eventlogtablefacade.h"
22
23
USING_NAMESPACE
24
25
#define LL  INT64_PRINTF_FORMAT
26
27
EventLogTableFacade::EventLogTableFacade(IEventLog *eventLog) : EventLogFacade(eventLog)
28
{
29
    setFilterMode(ALL_ENTRIES);
30
    setCustomFilter("*");
31
}
32
33
void EventLogTableFacade::synchronize(FileReader::FileChangedState change)
34
{
35
    if (change != FileReader::UNCHANGED) {
36
        EventLogFacade::synchronize(change);
37
        setFilterMode(filterMode);
38
    }
39
}
40
41
void EventLogTableFacade::setFilterMode(EventLogTableFilterMode filterMode)
42
{
43
    this->filterMode = filterMode;
44
45
    approximateNumberOfEntries = -1;
46
    lastMatchedEventNumber = -1;
47
    lastNumMatchingEventLogEntries = -1;
48
}
49
50
bool EventLogTableFacade::matchesFilter(EventLogEntry *eventLogEntry)
51
{
52
    switch (filterMode)
53
    {
54
        case ALL_ENTRIES:
55
            return true;
56
        case EVENT_AND_SEND_AND_MESSAGE_ENTRIES:
57
            return
58
                dynamic_cast<EventEntry *>(eventLogEntry) ||
59
                dynamic_cast<BeginSendEntry *>(eventLogEntry) ||
60
                dynamic_cast<EventLogMessageEntry *>(eventLogEntry);
61
        case EVENT_AND_MESSAGE_ENTRIES:
62
            return
63
                dynamic_cast<EventEntry *>(eventLogEntry) ||
64
                dynamic_cast<EventLogMessageEntry *>(eventLogEntry);
65
        case EVENT_ENTRIES:
66
            return dynamic_cast<EventEntry *>(eventLogEntry);
67
        case CUSTOM_ENTRIES:
68
            return matchExpression.matches(eventLogEntry);
69
        default:
70
            throw opp_runtime_error("Unknown event log table filter");
71
    }
72
}
73
74
int EventLogTableFacade::getNumMatchingEventLogEntries(IEvent *event)
75
{
76
    if (lastMatchedEventNumber == event->getEventNumber())
77
        return lastNumMatchingEventLogEntries;
78
    else {
79
        lastMatchedEventNumber = event->getEventNumber();
80
81
        switch (filterMode)
82
        {
83
            case ALL_ENTRIES:
84
                lastNumMatchingEventLogEntries = event->getNumEventLogEntries();
85
                break;
86
            case EVENT_AND_SEND_AND_MESSAGE_ENTRIES:
87
                lastNumMatchingEventLogEntries = event->getNumBeginSendEntries() + event->getNumEventLogMessages() + 1;
88
                break;
89
            case EVENT_AND_MESSAGE_ENTRIES:
90
                lastNumMatchingEventLogEntries = event->getNumEventLogMessages() + 1;
91
                break;
92
            case EVENT_ENTRIES:
93
                lastNumMatchingEventLogEntries = 1;
94
                break;
95
            case CUSTOM_ENTRIES:
96
                {
97
                    int count = 0;
98
                    int num = event->getNumEventLogEntries();
99
100
                    for (int i = 0; i < num; i++)
101
                        if (matchesFilter(event->getEventLogEntry(i)))
102
                            count++;
103
104
                    lastNumMatchingEventLogEntries = count;
105
                    break;
106
                }
107
            default:
108
                throw opp_runtime_error("Unknown event log table filter");
109
        }
110
111
        return lastNumMatchingEventLogEntries;
112
    }
113
}
114
115
EventLogEntry *EventLogTableFacade::getEventLogEntry(eventnumber_t eventNumber, int eventLogEntryIndex)
116
{
117
    IEvent *event = eventLog->getEventForEventNumber(eventNumber);
118
    Assert(event);
119
120
    return event->getEventLogEntry(eventLogEntryIndex);
121
}
122
123
EventLogEntry *EventLogTableFacade::getFirstEntry()
124
{
125
    IEvent *event = eventLog->getFirstEvent();
126
127
    if (!event)
128
        return NULL;
129
    else
130
        return getEntryInEvent(event, 0);
131
}
132
133
EventLogEntry *EventLogTableFacade::getLastEntry()
134
{
135
    IEvent *event = eventLog->getLastEvent();
136
137
    if (!event)
138
        return NULL;
139
    else
140
        return getEntryInEvent(event, getNumMatchingEventLogEntries(event) - 1);
141
}
142
143
EventLogEntry *EventLogTableFacade::getEntryAndDistance(EventLogEntry *sourceEventLogEntry, EventLogEntry *targetEventLogEntry, eventnumber_t distance, eventnumber_t& reachedDistance)
144
{
145
    Assert(sourceEventLogEntry);
146
    EventLogEntry *eventLogEntry = sourceEventLogEntry;
147
    reachedDistance = 0;
148
149
    int index = getEntryIndexInEvent(eventLogEntry);
150
    Assert(index >= 0);
151
152
    while (distance && eventLogEntry && eventLogEntry != targetEventLogEntry) {
153
        if (distance > 0) {
154
            eventLogEntry = getNextEntry(eventLogEntry, index);
155
            distance--;
156
            reachedDistance++;
157
        }
158
        else {
159
            eventLogEntry = getPreviousEntry(eventLogEntry, index);
160
            distance++;
161
            reachedDistance--;
162
        }
163
    }
164
165
    if (!eventLogEntry)
166
        reachedDistance += distance;
167
168
    return eventLogEntry;
169
}
170
171
EventLogEntry *EventLogTableFacade::getClosestEntryInEvent(EventLogEntry *eventLogEntry)
172
{
173
    Assert(eventLogEntry);
174
    IEvent *event = eventLogEntry->getEvent();
175
176
    for (int i = eventLogEntry->getEntryIndex(); i >= 0; i--) {
177
        eventLogEntry = event->getEventLogEntry(i);
178
179
        if (matchesFilter(eventLogEntry))
180
            return eventLogEntry;
181
    }
182
183
    throw opp_runtime_error("EventEntry should always match the filter");
184
}
185
186
EventLogEntry *EventLogTableFacade::getPreviousEntry(EventLogEntry *eventLogEntry, int& index)
187
{
188
    IEvent *event = eventLog->getEventForEventNumber(eventLogEntry->getEvent()->getEventNumber());
189
    index--;
190
191
    if (index == -1) {
192
        event = event->getPreviousEvent();
193
194
        if (event)
195
            index = getNumMatchingEventLogEntries(event) - 1;
196
    }
197
198
    if (!event)
199
        return NULL;
200
    else
201
        return getEntryInEvent(event, index);
202
}
203
204
EventLogEntry *EventLogTableFacade::getNextEntry(EventLogEntry *eventLogEntry, int& index)
205
{
206
    IEvent *event = eventLog->getEventForEventNumber(eventLogEntry->getEvent()->getEventNumber());
207
    index++;
208
209
    if (index == getNumMatchingEventLogEntries(event)) {
210
        event = event->getNextEvent();
211
        index = 0;
212
    }
213
214
    if (!event)
215
        return NULL;
216
    else
217
        return getEntryInEvent(event, index);
218
}
219
220
EventLogEntry *EventLogTableFacade::getEntryInEvent(IEvent *event, int index)
221
{
222
    Assert(index >= 0 && index < getNumMatchingEventLogEntries(event));
223
224
    int num = event->getNumEventLogEntries();
225
226
    for (int i = 0; i < num; i++)
227
    {
228
        EventLogEntry *eventLogEntry = event->getEventLogEntry(i);
229
230
        if (matchesFilter(eventLogEntry)) {
231
            if (index == 0)
232
                return eventLogEntry;
233
            else
234
                index--;
235
        }
236
    }
237
238
    throw opp_runtime_error("No event log entry with index: %d in event: %"INT64_PRINTF_FORMAT"d", index, event->getEventNumber());
239
}
240
241
int EventLogTableFacade::getEntryIndexInEvent(EventLogEntry *eventLogEntry)
242
{
243
    IEvent *event = eventLogEntry->getEvent();
244
    int index = 0;
245
    int num = event->getNumEventLogEntries();
246
247
    for (int i = 0; i < num; i++)
248
    {
249
        EventLogEntry *currentEventLogEntry = event->getEventLogEntry(i);
250
251
        if (matchesFilter(currentEventLogEntry)) {
252
            if (currentEventLogEntry == eventLogEntry)
253
                return index;
254
            else
255
                index++;
256
        }
257
    }
258
259
    throw opp_runtime_error("No event log entry found in event: %"INT64_PRINTF_FORMAT"d", event->getEventNumber());
260
}
261
262
eventnumber_t EventLogTableFacade::getDistanceToEntry(EventLogEntry *sourceEventLogEntry, EventLogEntry *targetEventLogEntry, eventnumber_t limit)
263
{
264
    eventnumber_t reachedDistance;
265
    getEntryAndDistance(sourceEventLogEntry, targetEventLogEntry, limit, reachedDistance);
266
    return reachedDistance;
267
}
268
269
eventnumber_t EventLogTableFacade::getDistanceToFirstEntry(EventLogEntry *eventLogEntry, eventnumber_t limit)
270
{
271
    eventnumber_t reachedDistance;
272
    getEntryAndDistance(eventLogEntry, getFirstEntry(), -limit, reachedDistance);
273
    return -reachedDistance;
274
}
275
276
eventnumber_t EventLogTableFacade::getDistanceToLastEntry(EventLogEntry *eventLogEntry, eventnumber_t limit)
277
{
278
    eventnumber_t reachedDistance;
279
    getEntryAndDistance(eventLogEntry, getLastEntry(), limit, reachedDistance);
280
    return reachedDistance;
281
}
282
283
EventLogEntry *EventLogTableFacade::getNeighbourEntry(EventLogEntry *eventLogEntry, eventnumber_t distance)
284
{
285
    eventnumber_t reachedDistance;
286
    return getEntryAndDistance(eventLogEntry, NULL, distance, reachedDistance);
287
}
288
289
double EventLogTableFacade::getApproximatePercentageForEntry(EventLogEntry *eventLogEntry)
290
{
291
    IEvent *beforeEvent = eventLogEntry->getEvent();
292
    IEvent *afterEvent = beforeEvent->getNextEvent();
293
    double beforePercentage = eventLog->getApproximatePercentageForEventNumber(beforeEvent->getEventNumber());
294
    double afterPercentage = afterEvent ? eventLog->getApproximatePercentageForEventNumber(afterEvent->getEventNumber()) : 1.0;
295
    int index = getEntryIndexInEvent(eventLogEntry);
296
297
    return beforePercentage + (afterPercentage - beforePercentage) * index / getNumMatchingEventLogEntries(beforeEvent);
298
}
299
300
EventLogEntry *EventLogTableFacade::getApproximateEventLogEntryAt(double percentage)
301
{
302
    Assert(0.0 <= percentage && percentage <= 1.0);
303
    if (percentage == 1) {
304
        IEvent* event = eventLog->getLastEvent();
305
306
        if (!event)
307
            return NULL;
308
        else
309
            return getEntryInEvent(event, getNumMatchingEventLogEntries(event) - 1);
310
    }
311
    else {
312
        IEvent *beforeEvent = eventLog->getApproximateEventAt(percentage);
313
314
        if (!beforeEvent)
315
            return NULL;
316
        else {
317
            double beforePercentage = eventLog->getApproximatePercentageForEventNumber(beforeEvent->getEventNumber());
318
            double afterPercentage = 1;
319
            IEvent *afterEvent = beforeEvent->getNextEvent();
320
321
            if (afterEvent)
322
                afterPercentage = eventLog->getApproximatePercentageForEventNumber(afterEvent->getEventNumber());
323
324
            if (percentage < beforePercentage || percentage > afterPercentage)
325
                return beforeEvent->getEventEntry();
326
            else {
327
                double entryPercentage = (percentage - beforePercentage) / (afterPercentage - beforePercentage);
328
                Assert(0.0 <= entryPercentage && entryPercentage <= 1.0);
329
                int index = (int) floor((getNumMatchingEventLogEntries(beforeEvent) - 1) * entryPercentage);
330
                return getEntryInEvent(beforeEvent, index);
331
            }
332
        }
333
    }
334
}
335
336
eventnumber_t EventLogTableFacade::getApproximateNumberOfEntries()
337
{
338
    if (approximateNumberOfEntries == -1)
339
    {
340
        IEvent *firstEvent = eventLog->getFirstEvent();
341
        IEvent *lastEvent = eventLog->getLastEvent();
342
343
        if (!firstEvent)
344
            approximateNumberOfEntries = 0;
345
        else
346
        {
347
            long sum = 0;
348
            long count = 0;
349
            int eventCount = 100;
350
351
            for (int i = 0; i < eventCount; i++)
352
            {
353
                if (firstEvent) {
354
                    sum += getNumMatchingEventLogEntries(firstEvent);
355
                    count++;
356
                    firstEvent = firstEvent->getNextEvent();
357
                }
358
359
                if (lastEvent) {
360
                    sum += getNumMatchingEventLogEntries(lastEvent);
361
                    count++;
362
                    lastEvent = lastEvent->getPreviousEvent();
363
                }
364
            }
365
366
            double average = (double)sum / count;
367
            approximateNumberOfEntries = (long)(eventLog->getApproximateNumberOfEvents() * average);
368
        }
369
    }
370
371
    return approximateNumberOfEntries;
372
}