Statistics
| Branch: | Revision:

root / src / eventlog / sequencechartfacade.cc @ 0596ce67

History | View | Annotate | Download (37.4 KB)

1 01873262 Georg Kunz
//=========================================================================
2
//  SEQUENCECHARTFACADE.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 <algorithm>
19
#include <set>
20
#include <math.h>
21
#include "lcgrandom.h"
22
#include "ievent.h"
23
#include "ieventlog.h"
24
#include "event.h"
25
#include "messagedependency.h"
26
#include "sequencechartfacade.h"
27
28
USING_NAMESPACE
29
30
SequenceChartFacade::SequenceChartFacade(IEventLog *eventLog) : EventLogFacade(eventLog)
31
{
32
    timelineMode = NONLINEAR;
33
    timelineCoordinateSystemVersion = -1;
34
    undefineTimelineCoordinateSystem();
35
36
    nonLinearMinimumTimelineCoordinateDelta = 0.1;
37
    setNonLinearFocus(calculateNonLinearFocus());
38 daf081df Simon Tenbusch
39
    smallestComplexity = -1;
40
    largestComplexity = -1;
41 ced95c57 Simon Tenbusch
42
    smallestDuration = -1;
43
    largestDuration = -1;
44 1c72663d Simon Tenbusch
45
    cachedParallelSet.clear();
46 a3b7e786 Simon Tenbusch
    cachedCriticalPath.clear();
47 01873262 Georg Kunz
}
48
49
void SequenceChartFacade::synchronize(FileReader::FileChangedState change)
50
{
51
    if (change != FileReader::UNCHANGED) {
52
        EventLogFacade::synchronize(change);
53
54
        setNonLinearFocus(calculateNonLinearFocus());
55
56
        if (timelineCoordinateOriginEventNumber != -1) {
57
            IEvent *event = eventLog->getEventForEventNumber(timelineCoordinateOriginEventNumber);
58
59
            if (event)
60
                relocateTimelineCoordinateSystem(event);
61
            else
62
                undefineTimelineCoordinateSystem();
63
        }
64
    }
65
}
66
67
double SequenceChartFacade::calculateNonLinearFocus()
68
{
69
    if (!eventLog->isEmpty()) {
70
        double lastEventSimulationTime = eventLog->getLastEvent()->getSimulationTime().dbl();
71
        double firstEventSimulationTime = eventLog->getFirstEvent()->getSimulationTime().dbl();
72
        double totalSimulationTimeDelta = lastEventSimulationTime - firstEventSimulationTime;
73
74
        if (totalSimulationTimeDelta == 0)
75
            totalSimulationTimeDelta = firstEventSimulationTime;
76
77
        if (totalSimulationTimeDelta == 0)
78
            return 1;
79
        else
80
            return totalSimulationTimeDelta / eventLog->getApproximateNumberOfEvents() / 10;
81
    }
82
    else
83
        return 1;
84
}
85
86
void SequenceChartFacade::setNonLinearMinimumTimelineCoordinateDelta(double value)
87
{
88
    Assert(value >= 0);
89
    nonLinearMinimumTimelineCoordinateDelta = value;
90
}
91
92
void SequenceChartFacade::setNonLinearFocus(double nonLinearFocus)
93
{
94
    Assert(nonLinearFocus >= 0);
95
    this->nonLinearFocus = nonLinearFocus;
96
}
97
98
void SequenceChartFacade::undefineTimelineCoordinateSystem()
99
{
100
    timelineCoordinateSystemVersion++;
101
    timelineCoordinateOriginEventNumber = timelineCoordinateRangeStartEventNumber = timelineCoordinateRangeEndEventNumber = -1;
102
    timelineCoordinateOriginSimulationTime = simtime_nil;
103 bcffd494 Simon Tenbusch
    timelineCoordinateOriginRealTime = 0;
104 01873262 Georg Kunz
}
105
106
void SequenceChartFacade::relocateTimelineCoordinateSystem(IEvent *event)
107
{
108
    Assert(event);
109
110
    timelineCoordinateSystemVersion++;
111
    timelineCoordinateOriginEventNumber = timelineCoordinateRangeStartEventNumber = timelineCoordinateRangeEndEventNumber = event->getEventNumber();
112
    timelineCoordinateOriginSimulationTime = event->getSimulationTime();
113 0596ce67 Simon Tenbusch
    timelineCoordinateOriginRealTime = event->getEarliestStartTime() / 1000000.0;
114 01873262 Georg Kunz
    event->cachedTimelineCoordinate = 0;
115
    event->cachedTimelineCoordinateSystemVersion = timelineCoordinateSystemVersion;
116
}
117
118
void SequenceChartFacade::setTimelineMode(TimelineMode timelineMode)
119
{
120
    this->timelineMode = timelineMode;
121
122
    if (timelineCoordinateOriginEventNumber != -1)
123
        relocateTimelineCoordinateSystem(eventLog->getEventForEventNumber(timelineCoordinateOriginEventNumber));
124
}
125
126
double SequenceChartFacade::IEvent_getTimelineCoordinate(ptr_t ptr)
127
{
128
    IEVENT_PTR(ptr);
129
    return getTimelineCoordinate((IEvent*)ptr);
130
}
131
132 382d8398 Simon Tenbusch
double SequenceChartFacade::IEvent_getTimelineEventEndCoordinate(ptr_t ptr)
133
{
134
    IEVENT_PTR(ptr);
135
    return getTimelineEventEndCoordinate((IEvent*)ptr);
136
}
137
138 01873262 Georg Kunz
double SequenceChartFacade::getTimelineCoordinateDelta(double simulationTimeDelta)
139
{
140
    Assert(nonLinearFocus > 0);
141
142
    if (timelineMode == STEP)
143
        return 1;
144
    else
145
        return nonLinearMinimumTimelineCoordinateDelta + (1 - nonLinearMinimumTimelineCoordinateDelta) * atan(fabs(simulationTimeDelta) / nonLinearFocus) / PI * 2;
146
}
147
148
double SequenceChartFacade::getTimelineCoordinate(ptr_t ptr, double lowerTimelineCoordinateCalculationLimit, double upperTimelineCoordinateCalculationLimit)
149
{
150
    IEVENT_PTR(ptr);
151
    return getTimelineCoordinate((IEvent *)ptr, lowerTimelineCoordinateCalculationLimit, upperTimelineCoordinateCalculationLimit);
152
}
153
154 382d8398 Simon Tenbusch
double SequenceChartFacade::getTimelineEventEndCoordinate(ptr_t ptr, double lowerTimelineCoordinateCalculationLimit, double upperTimelineCoordinateCalculationLimit)
155
{
156
    IEVENT_PTR(ptr);
157
    return getTimelineEventEndCoordinate((IEvent *)ptr, lowerTimelineCoordinateCalculationLimit, upperTimelineCoordinateCalculationLimit);
158
}
159
160 01873262 Georg Kunz
double SequenceChartFacade::getTimelineCoordinate(IEvent *event, double lowerTimelineCoordinateCalculationLimit, double upperTimelineCoordinateCalculationLimit)
161
{
162
    Assert(event);
163
    Assert(event->getEventLog() == eventLog);
164
    Assert(timelineCoordinateSystemVersion != -1);
165
    Assert(timelineCoordinateOriginEventNumber != -1);
166
167
    if (this->timelineCoordinateSystemVersion > event->cachedTimelineCoordinateSystemVersion) {
168
        double timelineCoordinate;
169
170
        switch (timelineMode) {
171 bcffd494 Simon Tenbusch
            case REAL_TIME:
172 0596ce67 Simon Tenbusch
                timelineCoordinate = ((event->getEarliestStartTime()/1000000.0 - timelineCoordinateOriginRealTime));
173 bcffd494 Simon Tenbusch
                break;
174 01873262 Georg Kunz
            case SIMULATION_TIME:
175
                timelineCoordinate = (event->getSimulationTime() - timelineCoordinateOriginSimulationTime).dbl();
176
                break;
177
            case EVENT_NUMBER:
178
                timelineCoordinate = event->getEventNumber() - timelineCoordinateOriginEventNumber;
179
                break;
180
            case STEP:
181
            case NONLINEAR:
182
                {
183
                    IEvent *previousEvent = NULL;
184
                    // do we go forward from end or backward from start of known range
185
                    bool forward = event->getEventNumber() > timelineCoordinateRangeEndEventNumber;
186
                    IEvent *currentEvent = eventLog->getEventForEventNumber(forward ? timelineCoordinateRangeEndEventNumber : timelineCoordinateRangeStartEventNumber);
187
188
                    Assert(event->getEventNumber() < timelineCoordinateRangeStartEventNumber || timelineCoordinateRangeEndEventNumber < event->getEventNumber());
189
190
                    // TODO: LONG RUNNING OPERATION
191
                    // does a linear search towards the event to calculate the non linear timeline coordinate
192
                    do {
193
                        eventLog->progress();
194
195
                        Assert(currentEvent);
196
                        previousEvent = currentEvent;
197
                        currentEvent = forward ? currentEvent->getNextEvent() : currentEvent->getPreviousEvent();
198
                        Assert(currentEvent);
199
200
                        simtime_t previousSimulationTime = previousEvent->getSimulationTime();
201
                        double previousTimelineCoordinate = previousEvent->cachedTimelineCoordinate;
202
                        simtime_t simulationTime = currentEvent->getSimulationTime();
203
                        double timelineCoordinateDelta = getTimelineCoordinateDelta((simulationTime - previousSimulationTime).dbl());
204
205
                        if (forward) {
206
                            timelineCoordinate = previousTimelineCoordinate + timelineCoordinateDelta;
207
208
                            if (timelineCoordinate > upperTimelineCoordinateCalculationLimit)
209
                                return NaN;
210
                        }
211
                        else {
212
                            timelineCoordinate = previousTimelineCoordinate - timelineCoordinateDelta;
213
214
                            if (timelineCoordinate < lowerTimelineCoordinateCalculationLimit)
215
                                return NaN;
216
                        }
217
218
                        currentEvent->cachedTimelineCoordinate = timelineCoordinate;
219
                        currentEvent->cachedTimelineCoordinateSystemVersion = timelineCoordinateSystemVersion;
220
                    }
221
                    while (currentEvent != event);
222
223
                    if (forward)
224
                        timelineCoordinateRangeEndEventNumber = event->getEventNumber();
225
                    else
226
                        timelineCoordinateRangeStartEventNumber = event->getEventNumber();
227
                }
228
                break;
229
            default:
230
                throw opp_runtime_error("Unknown timeline mode");
231
        }
232
233
        event->cachedTimelineCoordinate = timelineCoordinate;
234
        event->cachedTimelineCoordinateSystemVersion = timelineCoordinateSystemVersion;
235
    }
236
237
    return event->cachedTimelineCoordinate;
238
}
239
240 382d8398 Simon Tenbusch
double SequenceChartFacade::getTimelineEventEndCoordinate(IEvent *event, double lowerTimelineCoordinateCalculationLimit, double upperTimelineCoordinateCalculationLimit)
241
{
242
    Assert(event);
243
    Assert(event->getEventLog() == eventLog);
244
    if(!eventLog->isLegacyTrace()) {
245
        return getTimelineCoordinate(event);
246
    }
247
        double timelineEventEndCoordinate;
248
        switch (timelineMode) {
249 bcffd494 Simon Tenbusch
            case REAL_TIME:
250 0596ce67 Simon Tenbusch
                timelineEventEndCoordinate = (event->getEarliestProcessingTime()/ 1000000.0 - timelineCoordinateOriginRealTime) ;
251 bcffd494 Simon Tenbusch
                break;
252 382d8398 Simon Tenbusch
            case SIMULATION_TIME:
253
                timelineEventEndCoordinate = (event->getSimulationTime()+event->getEventEntry()->duration - timelineCoordinateOriginSimulationTime).dbl();
254
                break;
255
            default:
256
                return getTimelineCoordinate(event);
257
        }
258
    return timelineEventEndCoordinate;
259
}
260
261 01873262 Georg Kunz
double SequenceChartFacade::getCachedTimelineCoordinate(IEvent *event)
262
{
263
    Assert(event);
264
    Assert(timelineCoordinateSystemVersion != -1);
265
    Assert(timelineCoordinateOriginEventNumber != -1);
266
267
    if (this->timelineCoordinateSystemVersion > event->cachedTimelineCoordinateSystemVersion)
268
        return -1;
269
    else
270
        return event->cachedTimelineCoordinate;
271
}
272
273
IEvent *SequenceChartFacade::getEventForNonLinearTimelineCoordinate(double timelineCoordinate, bool &forward)
274
{
275
    Assert(timelineCoordinateOriginEventNumber != -1);
276
    IEvent *timelineCoordinateRangeStartEvent = eventLog->getEventForEventNumber(timelineCoordinateRangeStartEventNumber);
277
    IEvent *timelineCoordinateRangeEndEvent = eventLog->getEventForEventNumber(timelineCoordinateRangeEndEventNumber);
278
    IEvent *currentEvent;
279
280
    Assert(timelineCoordinateRangeStartEvent && timelineCoordinateRangeEndEvent);
281
282
    if (timelineCoordinate <= getTimelineCoordinate(timelineCoordinateRangeStartEvent)) {
283
        forward = false;
284
        currentEvent = timelineCoordinateRangeStartEvent;
285
    }
286
    else if (getTimelineCoordinate(timelineCoordinateRangeEndEvent) <= timelineCoordinate) {
287
        forward = true;
288
        currentEvent = timelineCoordinateRangeEndEvent;
289
    }
290
    else {
291
        forward = true;
292
        currentEvent = timelineCoordinateRangeStartEvent;
293
    }
294
295
    // TODO: LONG RUNNING OPERATION
296
    // does a linear search towards requested non linear timeline coordinate
297
    while (currentEvent && (forward ? getTimelineCoordinate(currentEvent) < timelineCoordinate :
298
                                      timelineCoordinate <= getTimelineCoordinate(currentEvent)))
299
    {
300
        eventLog->progress();
301
        currentEvent = forward ? currentEvent->getNextEvent() : currentEvent->getPreviousEvent();
302
    }
303
304
    return currentEvent;
305
}
306
307
IEvent *SequenceChartFacade::getLastEventNotAfterTimelineCoordinate(double timelineCoordinate)
308
{
309
    if (eventLog->isEmpty())
310
        return NULL;
311
312
    switch (timelineMode) {
313 bcffd494 Simon Tenbusch
        case REAL_TIME:
314
        {
315
            //TODO MAKE THIS MORE EFFICIENT (i.e. sorted data structure)!
316
            IEvent* res = eventLog->getFirstEvent();
317
            for (IEvent *current = eventLog->getFirstEvent(); current; current = current->getNextEvent()) {
318 0596ce67 Simon Tenbusch
                if ((double) current->getEarliestStartTime() / 1000000.0 < timelineCoordinate) {
319 bcffd494 Simon Tenbusch
                    if (current->getEarliestStartTime() > res->getEarliestStartTime()) {
320
                        res = current;
321
                    }
322
                }
323
            }
324
            return res;
325
        }
326 01873262 Georg Kunz
        case SIMULATION_TIME:
327
            return eventLog->getLastEventNotAfterSimulationTime(getSimulationTimeForTimelineCoordinate(timelineCoordinate));
328
        case EVENT_NUMBER:
329
            {
330
                eventnumber_t eventNumber = (eventnumber_t)floor(timelineCoordinate) + timelineCoordinateOriginEventNumber;
331
332
                if (eventNumber < 0)
333
                    return NULL;
334
                else
335
                    return eventLog->getLastEventNotAfterEventNumber(eventNumber);
336
            }
337
        case STEP:
338
        case NONLINEAR:
339
            {
340
                bool forward;
341
                IEvent *currentEvent = getEventForNonLinearTimelineCoordinate(timelineCoordinate, forward);
342
                currentEvent = forward ? (currentEvent ? currentEvent->getPreviousEvent() : eventLog->getLastEvent()) : currentEvent;
343
344
                Assert(!currentEvent || getTimelineCoordinate(currentEvent) <= timelineCoordinate);
345
                return currentEvent;
346
            }
347
        default:
348
            throw opp_runtime_error("Unknown timeline mode");
349
    }
350
}
351
352
IEvent *SequenceChartFacade::getFirstEventNotBeforeTimelineCoordinate(double timelineCoordinate)
353
{
354
    if (eventLog->isEmpty())
355
        return NULL;
356
357
    switch (timelineMode) {
358 bcffd494 Simon Tenbusch
        case REAL_TIME:
359
        {
360
            //TODO MAKE THIS MORE EFFICIENT (i.e. sorted data structure)!
361
            IEvent* res = eventLog->getLastEvent();
362
            for (IEvent *current = eventLog->getFirstEvent(); current; current = current->getNextEvent()) {
363 0596ce67 Simon Tenbusch
                if ((double) current->getEarliestStartTime() / 1000000.0 > timelineCoordinate) {
364 bcffd494 Simon Tenbusch
                    if (current->getEarliestStartTime() < res->getEarliestStartTime()) {
365
                        res = current;
366
                    }
367
                }
368
            }
369
            return res;
370
        }
371 01873262 Georg Kunz
        case SIMULATION_TIME:
372
            return eventLog->getFirstEventNotBeforeSimulationTime(getSimulationTimeForTimelineCoordinate(timelineCoordinate));
373
        case EVENT_NUMBER:
374
            {
375
                eventnumber_t eventNumber = (eventnumber_t)floor(timelineCoordinate) + timelineCoordinateOriginEventNumber;
376
377
                if (eventNumber < 0)
378
                    return eventLog->getFirstEvent();
379
                else
380
                    return eventLog->getFirstEventNotBeforeEventNumber(eventNumber);
381
            }
382
        case STEP:
383
        case NONLINEAR:
384
            {
385
                bool forward;
386
                IEvent *currentEvent = getEventForNonLinearTimelineCoordinate(timelineCoordinate, forward);
387
                currentEvent = forward ? currentEvent : (currentEvent ? currentEvent->getNextEvent() : eventLog->getFirstEvent());
388
389
                Assert(!currentEvent || getTimelineCoordinate(currentEvent) >= timelineCoordinate);
390
                return currentEvent;
391
            }
392
        default:
393
            throw opp_runtime_error("Unknown timeline mode");
394
    }
395
}
396
397
void SequenceChartFacade::extractSimulationTimesAndTimelineCoordinates(
398
    IEvent *event, IEvent *&nextEvent,
399
    simtime_t &eventSimulationTime, double &eventTimelineCoordinate,
400
    simtime_t &nextEventSimulationTime, double &nextEventTimelineCoordinate,
401
    simtime_t &simulationTimeDelta, double &timelineCoordinateDelta)
402
{
403
    // if before the first event
404
    if (event) {
405 0596ce67 Simon Tenbusch
        if (timelineMode==REAL_TIME) {
406
            eventSimulationTime = event->getEarliestStartTime() / 1000000.0;
407
        } else {
408
            eventSimulationTime = event->getSimulationTime();
409
        }
410 01873262 Georg Kunz
        eventTimelineCoordinate = getTimelineCoordinate(event);
411
    }
412
    else {
413
        eventSimulationTime = BigDecimal::Zero;
414
        IEvent *firstEvent = eventLog->getFirstEvent();
415
        eventTimelineCoordinate = getTimelineCoordinate(firstEvent);
416
417
        if (timelineMode == EVENT_NUMBER)
418
            eventTimelineCoordinate -= 1;
419 0596ce67 Simon Tenbusch
        else if (timelineMode == REAL_TIME)
420
            eventTimelineCoordinate -= getTimelineCoordinateDelta(0);
421 01873262 Georg Kunz
        else
422
            eventTimelineCoordinate -= getTimelineCoordinateDelta(firstEvent->getSimulationTime().dbl());
423
    }
424
425
    // linear approximation between two enclosing events
426
    nextEvent = event ? event->getNextEvent() : eventLog->getFirstEvent();
427
428
    if (nextEvent) {
429 0596ce67 Simon Tenbusch
        if(timelineMode==REAL_TIME) {
430
            nextEventSimulationTime = nextEvent->getEarliestStartTime() / 1000000.0;
431
        } else {
432
            nextEventSimulationTime = nextEvent->getSimulationTime();
433
        }
434
435 01873262 Georg Kunz
        nextEventTimelineCoordinate = getTimelineCoordinate(nextEvent);
436
437
        simulationTimeDelta = nextEventSimulationTime - eventSimulationTime;
438
        timelineCoordinateDelta = nextEventTimelineCoordinate - eventTimelineCoordinate;
439
    }
440
}
441
442
simtime_t SequenceChartFacade::getSimulationTimeForTimelineCoordinate(double timelineCoordinate, bool upperLimit)
443
{
444
    Assert(!isNaN(timelineCoordinate));
445
446
    if (eventLog->isEmpty())
447
        return BigDecimal::Zero;
448
449
    simtime_t simulationTime;
450
451
    switch (timelineMode)
452
    {
453 bcffd494 Simon Tenbusch
        case REAL_TIME:
454
        {
455 0596ce67 Simon Tenbusch
            simtime_t lastEventSimulationTime = (eventLog->getLastEvent()->getEarliestStartTime())/1000000.0;
456 bcffd494 Simon Tenbusch
            //NOTE: This sometimes crashes the Sequencechart because the returned value might be too big
457 0596ce67 Simon Tenbusch
            simulationTime = max(BigDecimal::Zero, min(lastEventSimulationTime, (timelineCoordinate + timelineCoordinateOriginRealTime)));
458 bcffd494 Simon Tenbusch
        }
459 0596ce67 Simon Tenbusch
        break;
460 01873262 Georg Kunz
        case SIMULATION_TIME:
461
            {
462
                simtime_t lastEventSimulationTime = eventLog->getLastEvent()->getSimulationTime();
463
                simulationTime = max(BigDecimal::Zero, min(lastEventSimulationTime, timelineCoordinate + timelineCoordinateOriginSimulationTime));
464
            }
465
            break;
466
        case EVENT_NUMBER:
467
        case STEP:
468
        case NONLINEAR:
469
            {
470
                IEvent *nextEvent;
471
                simtime_t eventSimulationTime, nextEventSimulationTime, simulationTimeDelta;
472
                double eventTimelineCoordinate, nextEventTimelineCoordinate, timelineCoordinateDelta;
473
474
                IEvent *event = getLastEventNotAfterTimelineCoordinate(timelineCoordinate);
475
                extractSimulationTimesAndTimelineCoordinates(event, nextEvent,
476
                                                             eventSimulationTime, eventTimelineCoordinate,
477
                                                             nextEventSimulationTime, nextEventTimelineCoordinate,
478
                                                             simulationTimeDelta, timelineCoordinateDelta);
479
480
                if (nextEvent) {
481
                    if (timelineCoordinateDelta == 0) {
482
                        // IMPORTANT NOTE: this is just an approximation
483
                        if (upperLimit)
484
                            simulationTime = nextEventSimulationTime;
485
                        else
486
                            simulationTime = eventSimulationTime;
487
                    }
488
                    else {
489
                        timelineCoordinate = std::max(eventTimelineCoordinate, std::min(nextEventTimelineCoordinate, timelineCoordinate));
490
                        simulationTime = eventSimulationTime + simulationTimeDelta * (timelineCoordinate - eventTimelineCoordinate) / timelineCoordinateDelta;
491
                        simulationTime = max(eventSimulationTime, min(nextEventSimulationTime, simulationTime));
492
                    }
493
                }
494
                else
495
                    simulationTime = eventSimulationTime;
496
            }
497
            break;
498
        default:
499
            throw opp_runtime_error("Unknown timeline mode");
500
    }
501
502
    Assert(!simulationTime.isNaN());
503
    Assert(simulationTime >= BigDecimal::Zero);
504 0596ce67 Simon Tenbusch
    if (timelineMode != REAL_TIME)
505
        Assert(simulationTime <= eventLog->getLastEvent()->getSimulationTime());
506 01873262 Georg Kunz
507
    return simulationTime;
508
}
509
510
double SequenceChartFacade::getTimelineCoordinateForSimulationTime(simtime_t simulationTime, bool upperLimit)
511
{
512
    Assert(!simulationTime.isNaN());
513
514
    if (eventLog->isEmpty())
515
        return 0;
516
517
    Assert(simulationTime >= BigDecimal::Zero);
518 0596ce67 Simon Tenbusch
    if (timelineMode != REAL_TIME)
519
        Assert(simulationTime <= eventLog->getLastEvent()->getSimulationTime());
520
521 01873262 Georg Kunz
522
    double timelineCoordinate;
523
524
    switch (timelineMode)
525
    {
526 bcffd494 Simon Tenbusch
        case REAL_TIME:
527 0596ce67 Simon Tenbusch
            //treat simulationTime as real time:
528
            timelineCoordinate = simulationTime.dbl() - timelineCoordinateOriginRealTime;
529
            break;
530 01873262 Georg Kunz
        case SIMULATION_TIME:
531
            timelineCoordinate = (simulationTime - timelineCoordinateOriginSimulationTime).dbl();
532
            break;
533
        case EVENT_NUMBER:
534
        case STEP:
535
        case NONLINEAR:
536
            {
537
                IEvent *nextEvent;
538
                simtime_t eventSimulationTime, nextEventSimulationTime, simulationTimeDelta;
539
                double eventTimelineCoordinate, nextEventTimelineCoordinate, timelineCoordinateDelta;
540
541
                IEvent *event = eventLog->getLastEventNotAfterSimulationTime(simulationTime);
542
                extractSimulationTimesAndTimelineCoordinates(event, nextEvent,
543
                                                             eventSimulationTime, eventTimelineCoordinate,
544
                                                             nextEventSimulationTime, nextEventTimelineCoordinate,
545
                                                             simulationTimeDelta, timelineCoordinateDelta);
546
547
                if (nextEvent) {
548
                    if (simulationTimeDelta == BigDecimal::Zero) {
549
                        // IMPORTANT NOTE: this is just an approximation
550
                        if (upperLimit)
551
                            timelineCoordinate = nextEventTimelineCoordinate;
552
                        else
553
                            timelineCoordinate = eventTimelineCoordinate;
554
                    }
555
                    else {
556
                        simulationTime = max(eventSimulationTime, min(nextEventSimulationTime, simulationTime));
557
                        timelineCoordinate = eventTimelineCoordinate + timelineCoordinateDelta * (simulationTime - eventSimulationTime).dbl() / simulationTimeDelta.dbl();
558
                        timelineCoordinate = std::max(eventTimelineCoordinate, std::min(nextEventTimelineCoordinate, timelineCoordinate));
559
                    }
560
                }
561
                else
562
                    timelineCoordinate = eventTimelineCoordinate;
563
            }
564
            break;
565
        default:
566
            throw opp_runtime_error("Unknown timeline mode");
567
    }
568
569
    Assert(!isNaN(timelineCoordinate));
570
571
    return timelineCoordinate;
572
}
573
574
double SequenceChartFacade::getTimelineCoordinateForSimulationTimeAndEventInModule(simtime_t simulationTime, int moduleId)
575
{
576
    IEvent *event = eventLog->getLastEventNotAfterSimulationTime(simulationTime);
577
578
    while (event && event->getSimulationTime() == simulationTime) {
579
        if (event->getModuleId() == moduleId)
580
            return getTimelineCoordinate(event);
581
582
        event = event->getNextEvent();
583
    }
584
585
    return getTimelineCoordinateForSimulationTime(simulationTime);
586
}
587
588
std::vector<ptr_t> *SequenceChartFacade::getModuleMethodBeginEntries(ptr_t startEventPtr, ptr_t endEventPtr)
589
{
590
    IEvent *startEvent = (IEvent *)startEventPtr;
591
    IEvent *endEvent = (IEvent *)endEventPtr;
592
    Assert(startEvent);
593
    Assert(endEvent);
594
    std::vector<ptr_t> *moduleMethodBeginEntries = new std::vector<ptr_t>();
595
596
    for (IEvent *event = startEvent;; event = event->getNextEvent()) {
597
        eventLog->progress();
598
599
        for (int i = 0; i < event->getNumEventLogEntries(); i++) {
600
            EventLogEntry *eventLogEntry = event->getEventLogEntry(i);
601
602
            if (dynamic_cast<ModuleMethodBeginEntry *>(eventLogEntry))
603
                moduleMethodBeginEntries->push_back((ptr_t)eventLogEntry);
604
        }
605
606
        if (event == endEvent)
607
            break;
608
    }
609
610
    return moduleMethodBeginEntries;
611
}
612
613
std::vector<ptr_t> *SequenceChartFacade::getIntersectingMessageDependencies(ptr_t startEventPtr, ptr_t endEventPtr)
614
{
615
    IEvent *startEvent = (IEvent *)startEventPtr;
616
    IEvent *endEvent = (IEvent *)endEventPtr;
617
    Assert(startEvent);
618
    Assert(endEvent);
619
    std::set<ptr_t> messageDependencies;
620
    eventnumber_t startEventNumber = startEvent->getEventNumber();
621
622
    // TODO: LONG RUNNING OPERATION
623
    // this might take a while if start and end events are far away from each other
624
    // if not completed then some dependencies will not be included
625
    for (IEvent *event = startEvent;; event = event->getNextEvent()) {
626
        eventLog->progress();
627
        IMessageDependencyList *causes = event->getCauses();
628
629
        for (IMessageDependencyList::iterator it = causes->begin(); it != causes->end(); it++) {
630
            IMessageDependency *messageDependency = *it;
631
632
            if (messageDependency->getCauseEventNumber() < startEventNumber)
633
                messageDependencies.insert((ptr_t)messageDependency);
634
        }
635
636
        IMessageDependencyList *consequences = event->getConsequences();
637
638
        for (IMessageDependencyList::iterator it = consequences->begin(); it != consequences->end(); it++)
639
            messageDependencies.insert((ptr_t)*it);
640
641
        if (event == endEvent)
642
            break;
643
    }
644
645
    std::vector<ptr_t> *result = new std::vector<ptr_t>;
646
    result->resize(messageDependencies.size());
647
    std::copy(messageDependencies.begin(), messageDependencies.end(), result->begin());
648
649
    return result;
650
}
651
652
std::vector<int> SequenceChartFacade::getApproximateMessageDependencyCountAdjacencyMatrix(std::map<int, int> *moduleIdToAxisIndexMap, int numberOfSamples, int messageSendWeight, int messageReuseWeight)
653
{
654
    LCGRandom lcgRandom;
655
    std::vector<int> adjacencyMatrix;
656
    std::set<int> axisIndexSet;
657
    std::map<eventnumber_t, IEvent *> eventNumberToEventMap;
658
659
    for (std::map<int, int>::iterator it = moduleIdToAxisIndexMap->begin(); it != moduleIdToAxisIndexMap->end(); it++)
660
        axisIndexSet.insert(it->second);
661
662
    int numberOfAxes = axisIndexSet.size();
663
    adjacencyMatrix.resize(numberOfAxes * numberOfAxes);
664
665
    for (int i = 0; i < numberOfSamples; i++)
666
    {
667
        // draw random
668
        double percentage = lcgRandom.next01();
669
        IEvent *event = eventLog->getApproximateEventAt(percentage);
670
        eventNumberToEventMap[event->getEventNumber()] = event;
671
672
        // look before origin
673
        if (timelineCoordinateOriginEventNumber != -1) {
674
            if (timelineCoordinateOriginEventNumber - i >= 0) {
675
                event = eventLog->getEventForEventNumber(timelineCoordinateOriginEventNumber - i);
676
                if (event)
677
                    eventNumberToEventMap[event->getEventNumber()] = event;
678
            }
679
680
            // look after origin
681
            event = eventLog->getEventForEventNumber(timelineCoordinateOriginEventNumber + i);
682
            if (event)
683
                eventNumberToEventMap[event->getEventNumber()] = event;
684
        }
685
    }
686
687
    for (std::map<eventnumber_t, IEvent *>::iterator it = eventNumberToEventMap.begin(); it != eventNumberToEventMap.end(); it++) {
688
        IEvent *event = it->second;
689
        IMessageDependencyList *causes = event->getCauses();
690
691
        for (IMessageDependencyList::iterator it = causes->begin(); it != causes->end(); it++) {
692
            IMessageDependency *messageDependency = *it;
693
            IEvent *causeEvent = messageDependency->getCauseEvent();
694
            IEvent *consequenceEvent = messageDependency->getConsequenceEvent();
695
            int weight = messageDependency->getIsReuse() ? messageReuseWeight : messageSendWeight;
696
697
            if (causeEvent && consequenceEvent && weight != 0) {
698
                int causeModuleId = causeEvent->getModuleId();
699
                int consequenceModuleId = consequenceEvent->getModuleId();
700
701
                std::map<int, int>::iterator causeModuleIdIt = moduleIdToAxisIndexMap->find(causeModuleId);
702
                std::map<int, int>::iterator consequenceModuleIdIt = moduleIdToAxisIndexMap->find(consequenceModuleId);
703
704
                if (causeModuleIdIt !=  moduleIdToAxisIndexMap->end() && consequenceModuleIdIt != moduleIdToAxisIndexMap->end())
705
                    adjacencyMatrix.at(causeModuleIdIt->second * numberOfAxes + consequenceModuleIdIt->second) += weight;
706
            }
707
        }
708
    }
709
710
    return adjacencyMatrix;
711
}
712 daf081df Simon Tenbusch
713
714
long SequenceChartFacade::getSmallestEventComplexity() {
715
    long complexity = 0;
716
    if (smallestComplexity < 0) {
717
        for (IEvent *event = eventLog->getFirstEvent();event != eventLog->getLastEvent(); event = event->getNextEvent()) {
718
             if (event->getEventEndEntry()) {
719
                 complexity = event->getEventEndEntry()->complexity;
720 61338f86 Simon Tenbusch
             } else {
721
                 continue;
722 daf081df Simon Tenbusch
             }
723
             if (complexity < smallestComplexity || smallestComplexity < 0) {
724
                 smallestComplexity = complexity;
725
             }
726
             if (complexity > largestComplexity || largestComplexity < 0) {
727
                 largestComplexity = complexity;
728
             }
729
        }
730
    }
731
    if (smallestComplexity < 0) {
732
        smallestComplexity = 0;
733
    }
734
    return smallestComplexity;
735
}
736
737
long SequenceChartFacade::getLargestEventComplexity() {
738
    if (largestComplexity < 0) {
739
        getSmallestEventComplexity();
740
    }
741
    if (largestComplexity < 0) {
742
        largestComplexity = 0;
743
    }
744
    return largestComplexity;
745
}
746 391dcea0 Simon Tenbusch
747 ced95c57 Simon Tenbusch
simtime_t SequenceChartFacade::getSmallestEventDuration() {
748
    simtime_t duration = 0;
749
    if (smallestDuration < 0) {
750
        for (IEvent *event = eventLog->getFirstEvent();event != eventLog->getLastEvent(); event = event->getNextEvent()) {
751
             if (event->getEventEntry()) {
752
                 duration = event->getEventEntry()->duration;
753
             } else {
754
                 continue;
755
             }
756
             if (duration < smallestDuration || smallestDuration < 0) {
757
                 smallestDuration = duration;
758
             }
759
             if (duration > largestDuration || largestDuration < 0) {
760
                 largestDuration = duration;
761
             }
762
        }
763
    }
764
    if (smallestDuration < 0) {
765
        smallestDuration = 0;
766
    }
767
    return smallestDuration;
768
}
769
770
simtime_t SequenceChartFacade::getLargestEventDuration() {
771
    if (largestDuration < 0) {
772
        getSmallestEventComplexity();
773
    }
774
    if (largestDuration < 0) {
775
        largestDuration = 0;
776
    }
777
    return largestDuration;
778
}
779
780 391dcea0 Simon Tenbusch
781
IEvent* SequenceChartFacade::getPreviousBottleneck(IEvent* e, unsigned int threshold) {
782
    IEvent* next = e->getPreviousEvent();
783
    while (next) {
784
        if (isBottleneck(next,threshold)) {
785
            return next;
786
        }
787
        next = next->getPreviousEvent();
788
    }
789
    return e;
790
}
791
792
IEvent* SequenceChartFacade::getNextBottleneck(IEvent* e, unsigned int threshold) {
793
    IEvent* next = e->getNextEvent();
794
    while (next) {
795
        if (isBottleneck(next,threshold)) {
796
            return next;
797
        }
798
        next = next->getNextEvent();
799
    }
800
    return e;
801
}
802
803
/*
804
 * Returns whether an event not part of a set of parallel events with more than treshold elements.
805
 */
806
bool SequenceChartFacade::isBottleneck(IEvent* event, unsigned int threshold)
807
{
808
    return getLargestParallelSetSize(event) <= threshold;
809
}
810 1c72663d Simon Tenbusch
/*
811
 * Returns whether event is in the largest parallel set of selected.
812
 */
813
bool SequenceChartFacade::isParallelWithEvent(IEvent* event, IEvent* selected) {
814
815
    if (lastSelected != selected) {
816
        getLargestParallelSet(selected, &cachedParallelSet);
817
    }
818
    return cachedParallelSet.find((ptr_t)event) != cachedParallelSet.end();
819
}
820 e2b044ac Simon Tenbusch
/*
821
 * Returns the size of the largest set that is parallel with event.
822
 *
823
 * Works by calculating the first parallel set which does not contain event by
824
 * successively going backwards through all events starting from event.
825
 */
826 391dcea0 Simon Tenbusch
unsigned int SequenceChartFacade::getLargestParallelSetSize(IEvent* event)
827
{
828
    IEvent* prev = event;
829
    std::set<ptr_t> parallelSet;
830
    parallelSet.clear();
831
    unsigned int previousSize = 0;
832
    while (prev)
833
    {
834
        previousSize = parallelSet.size();
835
836
        getParallelSet(prev, &parallelSet);
837
838
        if (parallelSet.find((ptr_t) event) == parallelSet.end())
839
        {
840 e2b044ac Simon Tenbusch
            //The current set does not contain event.
841
            //Therefore the previous set was the largest Parallel Set.
842 391dcea0 Simon Tenbusch
            break;
843
        }
844
        prev = prev->getPreviousEvent();
845
    }
846
    return previousSize;
847
}
848 e2b044ac Simon Tenbusch
/*
849
 * Returns the largest set that is parallel with event.
850
 *
851
 * Works by calculating the first parallel set which does not contain event by
852
 * successively going backwards through all events starting from event.
853
 */
854 1c72663d Simon Tenbusch
std::set<ptr_t>* SequenceChartFacade::getLargestParallelSet(IEvent* event, std::set<ptr_t>* parallelSet) {
855
    IEvent* prev = event;
856
    parallelSet->clear();
857
    while (prev)
858
    {
859
        getParallelSet(prev, parallelSet);
860
        if (parallelSet->find((ptr_t) event) == parallelSet->end())
861
        {
862 e2b044ac Simon Tenbusch
            //The current set does not contain event.
863
            //Therefore the previous set was the largest Parallel Set.
864 1c72663d Simon Tenbusch
            break;
865
        }
866
        prev = prev->getPreviousEvent();
867
    }
868
    if (prev != event) {
869
        getParallelSet(prev->getNextEvent(), parallelSet);
870
    }
871
    return parallelSet;
872
}
873
874 e2b044ac Simon Tenbusch
/*
875
 * Calculates a set of those events that start after event but are still in parallel to event.
876
 * This means that no other event must end before the latest start time in this set.
877
 */
878 391dcea0 Simon Tenbusch
void SequenceChartFacade::getParallelSet(IEvent* event,
879
        std::set<ptr_t>* parallelSet)
880
{
881
    IEvent* next = event->getNextEvent();
882
    simtime_t smallestParallelEndtime = getSmallestParallelEndtime(event);
883
    parallelSet->clear();
884
    parallelSet->insert((ptr_t) event);
885
    while (next)
886
    {
887
        if ((next->getSimulationTime() >= event->getSimulationTime())
888
                && (smallestParallelEndtime >= next->getSimulationTime()))
889
        {
890 95d5c2d3 Simon Tenbusch
            if(parallelSet->find((ptr_t)(next->getCauseEvent())) == parallelSet->end()) {
891
                parallelSet->insert((ptr_t) next);
892
            }
893 391dcea0 Simon Tenbusch
        }
894
        else
895
        {
896
            break;
897
        }
898
        next = next->getNextEvent();
899
    }
900
}
901 e2b044ac Simon Tenbusch
/*
902
 *
903
 */
904 391dcea0 Simon Tenbusch
simtime_t SequenceChartFacade::getSmallestParallelEndtime(IEvent* event)
905
{
906
    simtime_t minimum = event->getSimulationTime()
907
            + event->getEventEntry()->duration;
908
    for (IEvent *current = eventLog->getFirstEvent(); current; current
909
            = current->getNextEvent())
910
    {
911
        if (current->getSimulationTime() >= event->getSimulationTime())
912
        {
913
            if ((current->getSimulationTime()
914
                    + current->getEventEntry()->duration)
915
                    > event->getSimulationTime())
916
            {
917
                if (minimum > (current->getSimulationTime()
918
                        + current->getEventEntry()->duration))
919
                {
920
                    minimum = current->getSimulationTime()
921
                            + current->getEventEntry()->duration;
922
                }
923
            }
924
            if (current->getSimulationTime() > minimum)
925
            { // After this, no overlapping can follow
926
                break;
927
            }
928
        }
929
    }
930
    return minimum;
931
}
932 a3b7e786 Simon Tenbusch
933
/*
934
 * Determines whether the event lies on the critical path
935
 */
936
bool SequenceChartFacade::isOnCriticalPath(IEvent* event) {
937
    if (cachedCriticalPath.empty()) {
938
        calculateCriticalPath();
939
    }
940
    return (cachedCriticalPath.find((ptr_t)event) != cachedCriticalPath.end());
941
}
942
943
/*
944
 * Calculates the critical path of the run and stores it in the set cachedCriticalPath
945
 */
946
void SequenceChartFacade::calculateCriticalPath() {
947
    long maxEarliestProcessingTime = 0;
948
    IEvent* maxEarliestProcessingTimeEvent;
949
950
    for (IEvent *current = eventLog->getFirstEvent(); current; current = current->getNextEvent()) {
951
        simtime_t startTime = current->getSimulationTime();
952 e2b044ac Simon Tenbusch
        int moduleId = current->getModuleId();
953 a3b7e786 Simon Tenbusch
        if(current->getEventEndEntry()) {
954 bcffd494 Simon Tenbusch
            current->_earliestProcessingTime = current->getComplexity();
955 a3b7e786 Simon Tenbusch
        }
956 0596ce67 Simon Tenbusch
957
        current->setCriticalPredecessor(eventLog->getFirstEvent());
958
959 a3b7e786 Simon Tenbusch
        for (IEvent *antecessor = eventLog->getFirstEvent(); antecessor; antecessor = antecessor->getNextEvent()) {
960
            if(antecessor==current) {
961
                break; //We have to consider earlier events only
962
            }
963 d91c8332 Simon Tenbusch
            if(antecessor->getModuleId() != moduleId && current->getCauseEvent() != antecessor) {
964 a3b7e786 Simon Tenbusch
                continue; // Check if this is an antecesor
965
            }
966 bcffd494 Simon Tenbusch
            if(antecessor->_earliestProcessingTime+current->getComplexity() > current->_earliestProcessingTime) {
967
                current->_earliestProcessingTime = antecessor->_earliestProcessingTime+current->getComplexity();
968 0596ce67 Simon Tenbusch
                current->setCriticalPredecessor(antecessor);
969 a3b7e786 Simon Tenbusch
            }
970
        }
971
        // Memorize max event
972 bcffd494 Simon Tenbusch
        if (maxEarliestProcessingTime < current->_earliestProcessingTime) {
973
            maxEarliestProcessingTime = current->_earliestProcessingTime;
974 a3b7e786 Simon Tenbusch
            maxEarliestProcessingTimeEvent = current;
975
        }
976
    }
977 0596ce67 Simon Tenbusch
    //Now produce the convex hull of critical antecessors/predecessors:
978 a3b7e786 Simon Tenbusch
    cachedCriticalPath.clear();
979 0596ce67 Simon Tenbusch
    for (IEvent *predecessor = maxEarliestProcessingTimeEvent; predecessor ; predecessor = predecessor->getCriticalPredecessor()) {
980 a3b7e786 Simon Tenbusch
        cachedCriticalPath.insert((ptr_t)predecessor);
981 e2b044ac Simon Tenbusch
        if(predecessor->getEventNumber() == 0) {
982
            break;
983
        }
984 a3b7e786 Simon Tenbusch
    }
985
}