Statistics
| Branch: | Revision:

root / src / eventlog / sequencechartfacade.cc @ a2c79680

History | View | Annotate | Download (40 KB)

1
//=========================================================================
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

    
39
    smallestComplexity = -1;
40
    largestComplexity = -1;
41

    
42
    smallestDuration = -1;
43
    largestDuration = -1;
44

    
45
    biggestEarliestProcessingTime = 0;
46

    
47
    biggestEndTimeEvent = NULL;
48

    
49
    cachedParallelSet.clear();
50
    cachedCriticalPath.clear();
51
}
52

    
53
void SequenceChartFacade::synchronize(FileReader::FileChangedState change)
54
{
55
    if (change != FileReader::UNCHANGED) {
56
        EventLogFacade::synchronize(change);
57

    
58
        setNonLinearFocus(calculateNonLinearFocus());
59

    
60
        if (timelineCoordinateOriginEventNumber != -1) {
61
            IEvent *event = eventLog->getEventForEventNumber(timelineCoordinateOriginEventNumber);
62

    
63
            if (event)
64
                relocateTimelineCoordinateSystem(event);
65
            else
66
                undefineTimelineCoordinateSystem();
67
        }
68
    }
69
}
70

    
71
double SequenceChartFacade::calculateNonLinearFocus()
72
{
73
    if (!eventLog->isEmpty()) {
74
        double lastEventSimulationTime = eventLog->getLastEvent()->getSimulationTime().dbl();
75
        double firstEventSimulationTime = eventLog->getFirstEvent()->getSimulationTime().dbl();
76
        double totalSimulationTimeDelta = lastEventSimulationTime - firstEventSimulationTime;
77

    
78
        if (totalSimulationTimeDelta == 0)
79
            totalSimulationTimeDelta = firstEventSimulationTime;
80

    
81
        if (totalSimulationTimeDelta == 0)
82
            return 1;
83
        else
84
            return totalSimulationTimeDelta / eventLog->getApproximateNumberOfEvents() / 10;
85
    }
86
    else
87
        return 1;
88
}
89

    
90
void SequenceChartFacade::setNonLinearMinimumTimelineCoordinateDelta(double value)
91
{
92
    Assert(value >= 0);
93
    nonLinearMinimumTimelineCoordinateDelta = value;
94
}
95

    
96
void SequenceChartFacade::setNonLinearFocus(double nonLinearFocus)
97
{
98
    Assert(nonLinearFocus >= 0);
99
    this->nonLinearFocus = nonLinearFocus;
100
}
101

    
102
void SequenceChartFacade::undefineTimelineCoordinateSystem()
103
{
104
    timelineCoordinateSystemVersion++;
105
    timelineCoordinateOriginEventNumber = timelineCoordinateRangeStartEventNumber = timelineCoordinateRangeEndEventNumber = -1;
106
    timelineCoordinateOriginSimulationTime = simtime_nil;
107
    timelineCoordinateOriginRealTime = 0;
108
}
109

    
110
void SequenceChartFacade::relocateTimelineCoordinateSystem(IEvent *event)
111
{
112
    Assert(event);
113

    
114
    timelineCoordinateSystemVersion++;
115
    timelineCoordinateOriginEventNumber = timelineCoordinateRangeStartEventNumber = timelineCoordinateRangeEndEventNumber = event->getEventNumber();
116
    timelineCoordinateOriginSimulationTime = event->getSimulationTime();
117
    timelineCoordinateOriginRealTime = event->getEarliestStartTime() / 1000000.0;
118
    event->cachedTimelineCoordinate = 0;
119
    event->cachedTimelineCoordinateSystemVersion = timelineCoordinateSystemVersion;
120
}
121

    
122
void SequenceChartFacade::setTimelineMode(TimelineMode timelineMode)
123
{
124
    this->timelineMode = timelineMode;
125

    
126
    if (timelineCoordinateOriginEventNumber != -1)
127
        relocateTimelineCoordinateSystem(eventLog->getEventForEventNumber(timelineCoordinateOriginEventNumber));
128
}
129

    
130
double SequenceChartFacade::IEvent_getTimelineCoordinate(ptr_t ptr)
131
{
132
    IEVENT_PTR(ptr);
133
    return getTimelineCoordinate((IEvent*)ptr);
134
}
135

    
136
double SequenceChartFacade::IEvent_getTimelineEventEndCoordinate(ptr_t ptr)
137
{
138
    IEVENT_PTR(ptr);
139
    return getTimelineEventEndCoordinate((IEvent*)ptr);
140
}
141

    
142
double SequenceChartFacade::getTimelineCoordinateDelta(double simulationTimeDelta)
143
{
144
    Assert(nonLinearFocus > 0);
145

    
146
    if (timelineMode == STEP)
147
        return 1;
148
    else
149
        return nonLinearMinimumTimelineCoordinateDelta + (1 - nonLinearMinimumTimelineCoordinateDelta) * atan(fabs(simulationTimeDelta) / nonLinearFocus) / PI * 2;
150
}
151

    
152
double SequenceChartFacade::getTimelineCoordinate(ptr_t ptr, double lowerTimelineCoordinateCalculationLimit, double upperTimelineCoordinateCalculationLimit)
153
{
154
    IEVENT_PTR(ptr);
155
    return getTimelineCoordinate((IEvent *)ptr, lowerTimelineCoordinateCalculationLimit, upperTimelineCoordinateCalculationLimit);
156
}
157

    
158
double SequenceChartFacade::getTimelineEventEndCoordinate(ptr_t ptr, double lowerTimelineCoordinateCalculationLimit, double upperTimelineCoordinateCalculationLimit)
159
{
160
    IEVENT_PTR(ptr);
161
    return getTimelineEventEndCoordinate((IEvent *)ptr, lowerTimelineCoordinateCalculationLimit, upperTimelineCoordinateCalculationLimit);
162
}
163

    
164
double SequenceChartFacade::getTimelineCoordinate(IEvent *event, double lowerTimelineCoordinateCalculationLimit, double upperTimelineCoordinateCalculationLimit)
165
{
166
    Assert(event);
167
    Assert(event->getEventLog() == eventLog);
168
    Assert(timelineCoordinateSystemVersion != -1);
169
    Assert(timelineCoordinateOriginEventNumber != -1);
170

    
171
    if (this->timelineCoordinateSystemVersion > event->cachedTimelineCoordinateSystemVersion) {
172
        double timelineCoordinate;
173

    
174
        switch (timelineMode) {
175
            case REAL_TIME:
176
                timelineCoordinate = ((event->getEarliestStartTime()/1000000.0 - timelineCoordinateOriginRealTime));
177
                break;
178
            case SIMULATION_TIME:
179
                timelineCoordinate = (event->getSimulationTime() - timelineCoordinateOriginSimulationTime).dbl();
180
                break;
181
            case EVENT_NUMBER:
182
                timelineCoordinate = event->getEventNumber() - timelineCoordinateOriginEventNumber;
183
                break;
184
            case STEP:
185
            case NONLINEAR:
186
                {
187
                    IEvent *previousEvent = NULL;
188
                    // do we go forward from end or backward from start of known range
189
                    bool forward = event->getEventNumber() > timelineCoordinateRangeEndEventNumber;
190
                    IEvent *currentEvent = eventLog->getEventForEventNumber(forward ? timelineCoordinateRangeEndEventNumber : timelineCoordinateRangeStartEventNumber);
191

    
192
                    Assert(event->getEventNumber() < timelineCoordinateRangeStartEventNumber || timelineCoordinateRangeEndEventNumber < event->getEventNumber());
193

    
194
                    // TODO: LONG RUNNING OPERATION
195
                    // does a linear search towards the event to calculate the non linear timeline coordinate
196
                    do {
197
                        eventLog->progress();
198

    
199
                        Assert(currentEvent);
200
                        previousEvent = currentEvent;
201
                        currentEvent = forward ? currentEvent->getNextEvent() : currentEvent->getPreviousEvent();
202
                        Assert(currentEvent);
203

    
204
                        simtime_t previousSimulationTime = previousEvent->getSimulationTime();
205
                        double previousTimelineCoordinate = previousEvent->cachedTimelineCoordinate;
206
                        simtime_t simulationTime = currentEvent->getSimulationTime();
207
                        double timelineCoordinateDelta = getTimelineCoordinateDelta((simulationTime - previousSimulationTime).dbl());
208

    
209
                        if (forward) {
210
                            timelineCoordinate = previousTimelineCoordinate + timelineCoordinateDelta;
211

    
212
                            if (timelineCoordinate > upperTimelineCoordinateCalculationLimit)
213
                                return NaN;
214
                        }
215
                        else {
216
                            timelineCoordinate = previousTimelineCoordinate - timelineCoordinateDelta;
217

    
218
                            if (timelineCoordinate < lowerTimelineCoordinateCalculationLimit)
219
                                return NaN;
220
                        }
221

    
222
                        currentEvent->cachedTimelineCoordinate = timelineCoordinate;
223
                        currentEvent->cachedTimelineCoordinateSystemVersion = timelineCoordinateSystemVersion;
224
                    }
225
                    while (currentEvent != event);
226

    
227
                    if (forward)
228
                        timelineCoordinateRangeEndEventNumber = event->getEventNumber();
229
                    else
230
                        timelineCoordinateRangeStartEventNumber = event->getEventNumber();
231
                }
232
                break;
233
            default:
234
                throw opp_runtime_error("Unknown timeline mode");
235
        }
236

    
237
        event->cachedTimelineCoordinate = timelineCoordinate;
238
        event->cachedTimelineCoordinateSystemVersion = timelineCoordinateSystemVersion;
239
    }
240

    
241
    return event->cachedTimelineCoordinate;
242
}
243

    
244
double SequenceChartFacade::getTimelineEventEndCoordinate(IEvent *event, double lowerTimelineCoordinateCalculationLimit, double upperTimelineCoordinateCalculationLimit)
245
{
246
    Assert(event);
247
    Assert(event->getEventLog() == eventLog);
248
    if(!eventLog->isLegacyTrace()) {
249
        return getTimelineCoordinate(event);
250
    }
251
        double timelineEventEndCoordinate;
252
        switch (timelineMode) {
253
            case REAL_TIME:
254
                timelineEventEndCoordinate = (event->getEarliestProcessingTime()/ 1000000.0 - timelineCoordinateOriginRealTime) ;
255
                break;
256
            case SIMULATION_TIME:
257
                timelineEventEndCoordinate = (event->getSimulationTime()+event->getEventEntry()->duration - timelineCoordinateOriginSimulationTime).dbl();
258
                break;
259
            default:
260
                return getTimelineCoordinate(event);
261
        }
262
    return timelineEventEndCoordinate;
263
}
264

    
265
double SequenceChartFacade::getCachedTimelineCoordinate(IEvent *event)
266
{
267
    Assert(event);
268
    Assert(timelineCoordinateSystemVersion != -1);
269
    Assert(timelineCoordinateOriginEventNumber != -1);
270

    
271
    if (this->timelineCoordinateSystemVersion > event->cachedTimelineCoordinateSystemVersion)
272
        return -1;
273
    else
274
        return event->cachedTimelineCoordinate;
275
}
276

    
277
IEvent *SequenceChartFacade::getEventForNonLinearTimelineCoordinate(double timelineCoordinate, bool &forward)
278
{
279
    Assert(timelineCoordinateOriginEventNumber != -1);
280
    IEvent *timelineCoordinateRangeStartEvent = eventLog->getEventForEventNumber(timelineCoordinateRangeStartEventNumber);
281
    IEvent *timelineCoordinateRangeEndEvent = eventLog->getEventForEventNumber(timelineCoordinateRangeEndEventNumber);
282
    IEvent *currentEvent;
283

    
284
    Assert(timelineCoordinateRangeStartEvent && timelineCoordinateRangeEndEvent);
285

    
286
    if (timelineCoordinate <= getTimelineCoordinate(timelineCoordinateRangeStartEvent)) {
287
        forward = false;
288
        currentEvent = timelineCoordinateRangeStartEvent;
289
    }
290
    else if (getTimelineCoordinate(timelineCoordinateRangeEndEvent) <= timelineCoordinate) {
291
        forward = true;
292
        currentEvent = timelineCoordinateRangeEndEvent;
293
    }
294
    else {
295
        forward = true;
296
        currentEvent = timelineCoordinateRangeStartEvent;
297
    }
298

    
299
    // TODO: LONG RUNNING OPERATION
300
    // does a linear search towards requested non linear timeline coordinate
301
    while (currentEvent && (forward ? getTimelineCoordinate(currentEvent) < timelineCoordinate :
302
                                      timelineCoordinate <= getTimelineCoordinate(currentEvent)))
303
    {
304
        eventLog->progress();
305
        currentEvent = forward ? currentEvent->getNextEvent() : currentEvent->getPreviousEvent();
306
    }
307

    
308
    return currentEvent;
309
}
310

    
311
IEvent *SequenceChartFacade::getLastEventNotAfterTimelineCoordinate(double timelineCoordinate)
312
{
313
    if (eventLog->isEmpty())
314
        return NULL;
315

    
316
    switch (timelineMode) {
317
        case REAL_TIME:
318
        {
319
            //TODO MAKE THIS MORE EFFICIENT (i.e. sorted data structure)!
320
            IEvent* res = eventLog->getFirstEvent();
321
            for (IEvent *current = eventLog->getFirstEvent(); current; current = current->getNextEvent()) {
322
                if ((double) current->getEarliestStartTime() / 1000000.0 < timelineCoordinate) {
323
                    if (current->getEarliestStartTime() > res->getEarliestStartTime()) {
324
                        res = current;
325
                    }
326
                }
327
            }
328
            return res;
329
        }
330
        case SIMULATION_TIME:
331
            return eventLog->getLastEventNotAfterSimulationTime(getSimulationTimeForTimelineCoordinate(timelineCoordinate));
332
        case EVENT_NUMBER:
333
            {
334
                eventnumber_t eventNumber = (eventnumber_t)floor(timelineCoordinate) + timelineCoordinateOriginEventNumber;
335

    
336
                if (eventNumber < 0)
337
                    return NULL;
338
                else
339
                    return eventLog->getLastEventNotAfterEventNumber(eventNumber);
340
            }
341
        case STEP:
342
        case NONLINEAR:
343
            {
344
                bool forward;
345
                IEvent *currentEvent = getEventForNonLinearTimelineCoordinate(timelineCoordinate, forward);
346
                currentEvent = forward ? (currentEvent ? currentEvent->getPreviousEvent() : eventLog->getLastEvent()) : currentEvent;
347

    
348
                Assert(!currentEvent || getTimelineCoordinate(currentEvent) <= timelineCoordinate);
349
                return currentEvent;
350
            }
351
        default:
352
            throw opp_runtime_error("Unknown timeline mode");
353
    }
354
}
355

    
356
IEvent *SequenceChartFacade::getFirstEventNotBeforeTimelineCoordinate(double timelineCoordinate)
357
{
358
    if (eventLog->isEmpty())
359
        return NULL;
360

    
361
    switch (timelineMode) {
362
        case REAL_TIME:
363
        {
364
            //TODO MAKE THIS MORE EFFICIENT (i.e. sorted data structure)!
365
            IEvent* res = eventLog->getLastEvent();
366
            for (IEvent *current = eventLog->getFirstEvent(); current; current = current->getNextEvent()) {
367
                if ((double) current->getEarliestStartTime() / 1000000.0 > timelineCoordinate) {
368
                    if (current->getEarliestStartTime() < res->getEarliestStartTime()) {
369
                        res = current;
370
                    }
371
                }
372
            }
373
            return res;
374
        }
375
        case SIMULATION_TIME:
376
            return eventLog->getFirstEventNotBeforeSimulationTime(getSimulationTimeForTimelineCoordinate(timelineCoordinate));
377
        case EVENT_NUMBER:
378
            {
379
                eventnumber_t eventNumber = (eventnumber_t)floor(timelineCoordinate) + timelineCoordinateOriginEventNumber;
380

    
381
                if (eventNumber < 0)
382
                    return eventLog->getFirstEvent();
383
                else
384
                    return eventLog->getFirstEventNotBeforeEventNumber(eventNumber);
385
            }
386
        case STEP:
387
        case NONLINEAR:
388
            {
389
                bool forward;
390
                IEvent *currentEvent = getEventForNonLinearTimelineCoordinate(timelineCoordinate, forward);
391
                currentEvent = forward ? currentEvent : (currentEvent ? currentEvent->getNextEvent() : eventLog->getFirstEvent());
392

    
393
                Assert(!currentEvent || getTimelineCoordinate(currentEvent) >= timelineCoordinate);
394
                return currentEvent;
395
            }
396
        default:
397
            throw opp_runtime_error("Unknown timeline mode");
398
    }
399
}
400

    
401
void SequenceChartFacade::extractSimulationTimesAndTimelineCoordinates(
402
    IEvent *event, IEvent *&nextEvent,
403
    simtime_t &eventSimulationTime, double &eventTimelineCoordinate,
404
    simtime_t &nextEventSimulationTime, double &nextEventTimelineCoordinate,
405
    simtime_t &simulationTimeDelta, double &timelineCoordinateDelta)
406
{
407
    // if before the first event
408
    if (event) {
409
        if (timelineMode==REAL_TIME) {
410
            eventSimulationTime = event->getEarliestStartTime() / 1000000.0;
411
        } else {
412
            eventSimulationTime = event->getSimulationTime();
413
        }
414
        eventTimelineCoordinate = getTimelineCoordinate(event);
415
    }
416
    else {
417
        eventSimulationTime = BigDecimal::Zero;
418
        IEvent *firstEvent = eventLog->getFirstEvent();
419
        eventTimelineCoordinate = getTimelineCoordinate(firstEvent);
420

    
421
        if (timelineMode == EVENT_NUMBER)
422
            eventTimelineCoordinate -= 1;
423
        else if (timelineMode == REAL_TIME)
424
            eventTimelineCoordinate -= getTimelineCoordinateDelta(0);
425
        else
426
            eventTimelineCoordinate -= getTimelineCoordinateDelta(firstEvent->getSimulationTime().dbl());
427
    }
428

    
429
    // linear approximation between two enclosing events
430
    nextEvent = event ? event->getNextEvent() : eventLog->getFirstEvent();
431

    
432
    if (nextEvent) {
433
        if(timelineMode==REAL_TIME) {
434
            nextEventSimulationTime = nextEvent->getEarliestStartTime() / 1000000.0;
435
        } else {
436
            nextEventSimulationTime = nextEvent->getSimulationTime();
437
        }
438

    
439
        nextEventTimelineCoordinate = getTimelineCoordinate(nextEvent);
440

    
441
        simulationTimeDelta = nextEventSimulationTime - eventSimulationTime;
442
        timelineCoordinateDelta = nextEventTimelineCoordinate - eventTimelineCoordinate;
443
    }
444
}
445

    
446
simtime_t SequenceChartFacade::getSimulationTimeForTimelineCoordinate(double timelineCoordinate, bool upperLimit)
447
{
448
    Assert(!isNaN(timelineCoordinate));
449

    
450
    if (eventLog->isEmpty())
451
        return BigDecimal::Zero;
452

    
453
    simtime_t simulationTime;
454

    
455
    switch (timelineMode)
456
    {
457
        case REAL_TIME:
458
        {
459
            simulationTime = max(BigDecimal::Zero, min(biggestEarliestProcessingTime, (timelineCoordinate + timelineCoordinateOriginRealTime)));
460
        }
461
        break;
462
        case SIMULATION_TIME:
463
            {
464
                IEvent* largestEvent = (IEvent*) getLargestEndtimeInEventRange((ptr_t)(eventLog->getFirstEvent()),(ptr_t)(eventLog->getLastEvent()), upperLimit);
465
                simtime_t lastEventSimulationTime= largestEvent->getSimulationTime() + largestEvent->getEventEntry()->duration;
466
                simulationTime = max(BigDecimal::Zero, min(lastEventSimulationTime, timelineCoordinate + timelineCoordinateOriginSimulationTime));
467
            }
468
            break;
469
        case EVENT_NUMBER:
470
        case STEP:
471
        case NONLINEAR:
472
            {
473
                IEvent *nextEvent;
474
                simtime_t eventSimulationTime, nextEventSimulationTime, simulationTimeDelta;
475
                double eventTimelineCoordinate, nextEventTimelineCoordinate, timelineCoordinateDelta;
476

    
477
                IEvent *event = getLastEventNotAfterTimelineCoordinate(timelineCoordinate);
478
                extractSimulationTimesAndTimelineCoordinates(event, nextEvent,
479
                                                             eventSimulationTime, eventTimelineCoordinate,
480
                                                             nextEventSimulationTime, nextEventTimelineCoordinate,
481
                                                             simulationTimeDelta, timelineCoordinateDelta);
482

    
483
                if (nextEvent) {
484
                    if (timelineCoordinateDelta == 0) {
485
                        // IMPORTANT NOTE: this is just an approximation
486
                        if (upperLimit)
487
                            simulationTime = nextEventSimulationTime;
488
                        else
489
                            simulationTime = eventSimulationTime;
490
                    }
491
                    else {
492
                        timelineCoordinate = std::max(eventTimelineCoordinate, std::min(nextEventTimelineCoordinate, timelineCoordinate));
493
                        simulationTime = eventSimulationTime + simulationTimeDelta * (timelineCoordinate - eventTimelineCoordinate) / timelineCoordinateDelta;
494
                        simulationTime = max(eventSimulationTime, min(nextEventSimulationTime, simulationTime));
495
                    }
496
                }
497
                else
498
                    simulationTime = eventSimulationTime;
499
            }
500
            break;
501
        default:
502
            throw opp_runtime_error("Unknown timeline mode");
503
    }
504

    
505
    Assert(!simulationTime.isNaN());
506
    Assert(simulationTime >= BigDecimal::Zero);
507
    /*if (timelineMode != REAL_TIME)
508
        Assert(simulationTime <= eventLog->getLastEvent()->getSimulationTime());
509
    */
510
    return simulationTime;
511
}
512

    
513
double SequenceChartFacade::getTimelineCoordinateForSimulationTime(simtime_t simulationTime, bool upperLimit)
514
{
515
    Assert(!simulationTime.isNaN());
516

    
517
    if (eventLog->isEmpty())
518
        return 0;
519

    
520
    Assert(simulationTime >= BigDecimal::Zero);
521
    /*if (timelineMode != REAL_TIME)
522
        Assert(simulationTime <= eventLog->getLastEvent()->getSimulationTime());
523
    */
524

    
525
    double timelineCoordinate;
526

    
527
    switch (timelineMode)
528
    {
529
        case REAL_TIME:
530
            //treat simulationTime as real time:
531
            timelineCoordinate = simulationTime.dbl() - timelineCoordinateOriginRealTime;
532
            break;
533
        case SIMULATION_TIME:
534
            timelineCoordinate = (simulationTime - timelineCoordinateOriginSimulationTime).dbl();
535
            break;
536
        case EVENT_NUMBER:
537
        case STEP:
538
        case NONLINEAR:
539
            {
540
                IEvent *nextEvent;
541
                simtime_t eventSimulationTime, nextEventSimulationTime, simulationTimeDelta;
542
                double eventTimelineCoordinate, nextEventTimelineCoordinate, timelineCoordinateDelta;
543

    
544
                IEvent *event = eventLog->getLastEventNotAfterSimulationTime(simulationTime);
545
                extractSimulationTimesAndTimelineCoordinates(event, nextEvent,
546
                                                             eventSimulationTime, eventTimelineCoordinate,
547
                                                             nextEventSimulationTime, nextEventTimelineCoordinate,
548
                                                             simulationTimeDelta, timelineCoordinateDelta);
549

    
550
                if (nextEvent) {
551
                    if (simulationTimeDelta == BigDecimal::Zero) {
552
                        // IMPORTANT NOTE: this is just an approximation
553
                        if (upperLimit)
554
                            timelineCoordinate = nextEventTimelineCoordinate;
555
                        else
556
                            timelineCoordinate = eventTimelineCoordinate;
557
                    }
558
                    else {
559
                        simulationTime = max(eventSimulationTime, min(nextEventSimulationTime, simulationTime));
560
                        timelineCoordinate = eventTimelineCoordinate + timelineCoordinateDelta * (simulationTime - eventSimulationTime).dbl() / simulationTimeDelta.dbl();
561
                        timelineCoordinate = std::max(eventTimelineCoordinate, std::min(nextEventTimelineCoordinate, timelineCoordinate));
562
                    }
563
                }
564
                else
565
                    timelineCoordinate = eventTimelineCoordinate;
566
            }
567
            break;
568
        default:
569
            throw opp_runtime_error("Unknown timeline mode");
570
    }
571

    
572
    Assert(!isNaN(timelineCoordinate));
573

    
574
    return timelineCoordinate;
575
}
576

    
577
double SequenceChartFacade::getTimelineCoordinateForSimulationTimeAndEventInModule(simtime_t simulationTime, int moduleId)
578
{
579
    IEvent *event = eventLog->getLastEventNotAfterSimulationTime(simulationTime);
580

    
581
    while (event && event->getSimulationTime() == simulationTime) {
582
        if (event->getModuleId() == moduleId)
583
            return getTimelineCoordinate(event);
584

    
585
        event = event->getNextEvent();
586
    }
587

    
588
    return getTimelineCoordinateForSimulationTime(simulationTime);
589
}
590

    
591
std::vector<ptr_t> *SequenceChartFacade::getModuleMethodBeginEntries(ptr_t startEventPtr, ptr_t endEventPtr)
592
{
593
    IEvent *startEvent = (IEvent *)startEventPtr;
594
    IEvent *endEvent = (IEvent *)endEventPtr;
595
    Assert(startEvent);
596
    Assert(endEvent);
597
    std::vector<ptr_t> *moduleMethodBeginEntries = new std::vector<ptr_t>();
598

    
599
    for (IEvent *event = startEvent;; event = event->getNextEvent()) {
600
        eventLog->progress();
601

    
602
        for (int i = 0; i < event->getNumEventLogEntries(); i++) {
603
            EventLogEntry *eventLogEntry = event->getEventLogEntry(i);
604

    
605
            if (dynamic_cast<ModuleMethodBeginEntry *>(eventLogEntry))
606
                moduleMethodBeginEntries->push_back((ptr_t)eventLogEntry);
607
        }
608

    
609
        if (event == endEvent)
610
            break;
611
    }
612

    
613
    return moduleMethodBeginEntries;
614
}
615

    
616
std::vector<ptr_t> *SequenceChartFacade::getIntersectingMessageDependencies(ptr_t startEventPtr, ptr_t endEventPtr)
617
{
618
    IEvent *startEvent = (IEvent *)startEventPtr;
619
    IEvent *endEvent = (IEvent *)endEventPtr;
620
    Assert(startEvent);
621
    Assert(endEvent);
622
    std::set<ptr_t> messageDependencies;
623
    eventnumber_t startEventNumber = startEvent->getEventNumber();
624

    
625
    // TODO: LONG RUNNING OPERATION
626
    // this might take a while if start and end events are far away from each other
627
    // if not completed then some dependencies will not be included
628
    for (IEvent *event = startEvent;; event = event->getNextEvent()) {
629
        eventLog->progress();
630
        IMessageDependencyList *causes = event->getCauses();
631

    
632
        for (IMessageDependencyList::iterator it = causes->begin(); it != causes->end(); it++) {
633
            IMessageDependency *messageDependency = *it;
634

    
635
            if (messageDependency->getCauseEventNumber() < startEventNumber)
636
                messageDependencies.insert((ptr_t)messageDependency);
637
        }
638

    
639
        IMessageDependencyList *consequences = event->getConsequences();
640

    
641
        for (IMessageDependencyList::iterator it = consequences->begin(); it != consequences->end(); it++)
642
            messageDependencies.insert((ptr_t)*it);
643

    
644
        if (event == endEvent)
645
            break;
646
    }
647

    
648
    std::vector<ptr_t> *result = new std::vector<ptr_t>;
649
    result->resize(messageDependencies.size());
650
    std::copy(messageDependencies.begin(), messageDependencies.end(), result->begin());
651

    
652
    return result;
653
}
654

    
655
std::vector<int> SequenceChartFacade::getApproximateMessageDependencyCountAdjacencyMatrix(std::map<int, int> *moduleIdToAxisIndexMap, int numberOfSamples, int messageSendWeight, int messageReuseWeight)
656
{
657
    LCGRandom lcgRandom;
658
    std::vector<int> adjacencyMatrix;
659
    std::set<int> axisIndexSet;
660
    std::map<eventnumber_t, IEvent *> eventNumberToEventMap;
661

    
662
    for (std::map<int, int>::iterator it = moduleIdToAxisIndexMap->begin(); it != moduleIdToAxisIndexMap->end(); it++)
663
        axisIndexSet.insert(it->second);
664

    
665
    int numberOfAxes = axisIndexSet.size();
666
    adjacencyMatrix.resize(numberOfAxes * numberOfAxes);
667

    
668
    for (int i = 0; i < numberOfSamples; i++)
669
    {
670
        // draw random
671
        double percentage = lcgRandom.next01();
672
        IEvent *event = eventLog->getApproximateEventAt(percentage);
673
        eventNumberToEventMap[event->getEventNumber()] = event;
674

    
675
        // look before origin
676
        if (timelineCoordinateOriginEventNumber != -1) {
677
            if (timelineCoordinateOriginEventNumber - i >= 0) {
678
                event = eventLog->getEventForEventNumber(timelineCoordinateOriginEventNumber - i);
679
                if (event)
680
                    eventNumberToEventMap[event->getEventNumber()] = event;
681
            }
682

    
683
            // look after origin
684
            event = eventLog->getEventForEventNumber(timelineCoordinateOriginEventNumber + i);
685
            if (event)
686
                eventNumberToEventMap[event->getEventNumber()] = event;
687
        }
688
    }
689

    
690
    for (std::map<eventnumber_t, IEvent *>::iterator it = eventNumberToEventMap.begin(); it != eventNumberToEventMap.end(); it++) {
691
        IEvent *event = it->second;
692
        IMessageDependencyList *causes = event->getCauses();
693

    
694
        for (IMessageDependencyList::iterator it = causes->begin(); it != causes->end(); it++) {
695
            IMessageDependency *messageDependency = *it;
696
            IEvent *causeEvent = messageDependency->getCauseEvent();
697
            IEvent *consequenceEvent = messageDependency->getConsequenceEvent();
698
            int weight = messageDependency->getIsReuse() ? messageReuseWeight : messageSendWeight;
699

    
700
            if (causeEvent && consequenceEvent && weight != 0) {
701
                int causeModuleId = causeEvent->getModuleId();
702
                int consequenceModuleId = consequenceEvent->getModuleId();
703

    
704
                std::map<int, int>::iterator causeModuleIdIt = moduleIdToAxisIndexMap->find(causeModuleId);
705
                std::map<int, int>::iterator consequenceModuleIdIt = moduleIdToAxisIndexMap->find(consequenceModuleId);
706

    
707
                if (causeModuleIdIt !=  moduleIdToAxisIndexMap->end() && consequenceModuleIdIt != moduleIdToAxisIndexMap->end())
708
                    adjacencyMatrix.at(causeModuleIdIt->second * numberOfAxes + consequenceModuleIdIt->second) += weight;
709
            }
710
        }
711
    }
712

    
713
    return adjacencyMatrix;
714
}
715

    
716

    
717
long SequenceChartFacade::getSmallestEventComplexity() {
718
    long complexity = 0;
719
    if (smallestComplexity < 0) {
720
        for (IEvent *event = eventLog->getFirstEvent();event != eventLog->getLastEvent(); event = event->getNextEvent()) {
721
             if (event->getEventEndEntry()) {
722
                 complexity = event->getEventEndEntry()->complexity;
723
             } else {
724
                 continue;
725
             }
726
             if (complexity < smallestComplexity || smallestComplexity < 0) {
727
                 smallestComplexity = complexity;
728
             }
729
             if (complexity > largestComplexity || largestComplexity < 0) {
730
                 largestComplexity = complexity;
731
             }
732
        }
733
    }
734
    if (smallestComplexity < 0) {
735
        smallestComplexity = 0;
736
    }
737
    return smallestComplexity;
738
}
739

    
740
long SequenceChartFacade::getLargestEventComplexity() {
741
    if (largestComplexity < 0) {
742
        getSmallestEventComplexity();
743
    }
744
    if (largestComplexity < 0) {
745
        largestComplexity = 0;
746
    }
747
    return largestComplexity;
748
}
749

    
750
simtime_t SequenceChartFacade::getSmallestEventDuration() {
751
    simtime_t duration = 0;
752
    if (smallestDuration < 0) {
753
        for (IEvent *event = eventLog->getFirstEvent();event != eventLog->getLastEvent(); event = event->getNextEvent()) {
754
             if (event->getEventEntry()) {
755
                 duration = event->getEventEntry()->duration;
756
             } else {
757
                 continue;
758
             }
759
             if (duration < smallestDuration || smallestDuration < 0) {
760
                 smallestDuration = duration;
761
             }
762
             if (duration > largestDuration || largestDuration < 0) {
763
                 largestDuration = duration;
764
             }
765
        }
766
    }
767
    if (smallestDuration < 0) {
768
        smallestDuration = 0;
769
    }
770
    return smallestDuration;
771
}
772

    
773
simtime_t SequenceChartFacade::getLargestEventDuration() {
774
    if (largestDuration < 0) {
775
        getSmallestEventComplexity();
776
    }
777
    if (largestDuration < 0) {
778
        largestDuration = 0;
779
    }
780
    return largestDuration;
781
}
782

    
783

    
784
IEvent* SequenceChartFacade::getPreviousBottleneck(IEvent* e, unsigned int threshold) {
785
    IEvent* next = e->getPreviousEvent();
786
    while (next) {
787
        if (isBottleneck(next,threshold)) {
788
            return next;
789
        }
790
        next = next->getPreviousEvent();
791
    }
792
    return e;
793
}
794

    
795
IEvent* SequenceChartFacade::getNextBottleneck(IEvent* e, unsigned int threshold) {
796
    IEvent* next = e->getNextEvent();
797
    while (next) {
798
        if (isBottleneck(next,threshold)) {
799
            return next;
800
        }
801
        next = next->getNextEvent();
802
    }
803
    return e;
804
}
805

    
806
/*
807
 * Returns whether an event not part of a set of parallel events with more than treshold elements.
808
 */
809
bool SequenceChartFacade::isBottleneck(IEvent* event, unsigned int threshold)
810
{
811
    return getLargestParallelSetSize(event) <= threshold;
812
}
813
/*
814
 * Returns whether event is in the largest parallel set of selected.
815
 */
816
bool SequenceChartFacade::isParallelWithEvent(IEvent* event, IEvent* selected) {
817

    
818
    if (lastSelected != selected) {
819
        getLargestParallelSet(selected, &cachedParallelSet);
820
    }
821
    return cachedParallelSet.find((ptr_t)event) != cachedParallelSet.end();
822
}
823
/*
824
 * Returns the size of the largest set that is parallel with event.
825
 *
826
 * Works by calculating the first parallel set which does not contain event by
827
 * successively going backwards through all events starting from event.
828
 */
829
unsigned int SequenceChartFacade::getLargestParallelSetSize(IEvent* event)
830
{
831
    IEvent* prev = event;
832
    std::set<ptr_t> parallelSet;
833
    parallelSet.clear();
834
    unsigned int previousSize = 0;
835
    while (prev)
836
    {
837
        previousSize = parallelSet.size();
838

    
839
        getParallelSet(prev, &parallelSet);
840

    
841
        if (parallelSet.find((ptr_t) event) == parallelSet.end())
842
        {
843
            //The current set does not contain event.
844
            //Therefore the previous set was the largest Parallel Set.
845
            break;
846
        }
847
        prev = prev->getPreviousEvent();
848
    }
849
    return previousSize;
850
}
851
/*
852
 * Returns the largest set that is parallel with event.
853
 *
854
 * Works by calculating the first parallel set which does not contain event by
855
 * successively going backwards through all events starting from event.
856
 */
857
std::set<ptr_t>* SequenceChartFacade::getLargestParallelSet(IEvent* event, std::set<ptr_t>* parallelSet) {
858
    IEvent* prev = event;
859
    parallelSet->clear();
860
    while (prev)
861
    {
862
        getParallelSet(prev, parallelSet);
863
        if (parallelSet->find((ptr_t) event) == parallelSet->end())
864
        {
865
            //The current set does not contain event.
866
            //Therefore the previous set was the largest Parallel Set.
867
            break;
868
        }
869
        prev = prev->getPreviousEvent();
870
    }
871
    if (prev != event) {
872
        getParallelSet(prev->getNextEvent(), parallelSet);
873
    }
874
    return parallelSet;
875
}
876

    
877
/*
878
 * Calculates a set of those events that start after event but are still in parallel to event.
879
 * This means that no other event must end before the latest start time in this set.
880
 */
881
void SequenceChartFacade::getParallelSet(IEvent* event,
882
        std::set<ptr_t>* parallelSet)
883
{
884
    IEvent* next = event->getNextEvent();
885
    simtime_t smallestParallelEndtime = getSmallestParallelEndtime(event);
886
    parallelSet->clear();
887
    parallelSet->insert((ptr_t) event);
888
    while (next)
889
    {
890
        if ((next->getSimulationTime() >= event->getSimulationTime())
891
                && (smallestParallelEndtime >= next->getSimulationTime()))
892
        {
893
            if(parallelSet->find((ptr_t)(next->getCauseEvent())) == parallelSet->end()) {
894
                parallelSet->insert((ptr_t) next);
895
            }
896
        }
897
        else
898
        {
899
            break;
900
        }
901
        next = next->getNextEvent();
902
    }
903
}
904
/*
905
 *
906
 */
907
simtime_t SequenceChartFacade::getSmallestParallelEndtime(IEvent* event)
908
{
909
    simtime_t minimum = event->getSimulationTime()
910
            + event->getEventEntry()->duration;
911
    for (IEvent *current = eventLog->getFirstEvent(); current; current
912
            = current->getNextEvent())
913
    {
914
        if (current->getSimulationTime() >= event->getSimulationTime())
915
        {
916
            if ((current->getSimulationTime()
917
                    + current->getEventEntry()->duration)
918
                    > event->getSimulationTime())
919
            {
920
                if (minimum > (current->getSimulationTime()
921
                        + current->getEventEntry()->duration))
922
                {
923
                    minimum = current->getSimulationTime()
924
                            + current->getEventEntry()->duration;
925
                }
926
            }
927
            if (current->getSimulationTime() > minimum)
928
            { // After this, no overlapping can follow
929
                break;
930
            }
931
        }
932
    }
933
    return minimum;
934
}
935

    
936
/*
937
 * Determines whether the event lies on the critical path
938
 */
939
bool SequenceChartFacade::isOnCriticalPath(IEvent* event) {
940
    if (cachedCriticalPath.empty()) {
941
        calculateCriticalPath();
942
    }
943
    return (cachedCriticalPath.find((ptr_t)event) != cachedCriticalPath.end());
944
}
945

    
946
/*
947
 * Calculates the critical path of the run and stores it in the set cachedCriticalPath
948
 */
949
void SequenceChartFacade::calculateCriticalPath() {
950
    long maxEarliestProcessingTime = 0;
951
    IEvent* maxEarliestProcessingTimeEvent;
952

    
953
    for (IEvent *current = eventLog->getFirstEvent(); current; current = current->getNextEvent()) {
954
        simtime_t startTime = current->getSimulationTime();
955
        int moduleId = current->getModuleId();
956
        if(current->getEventEndEntry()) {
957
            current->_earliestProcessingTime = current->getComplexity();
958
        }
959

    
960
        current->setCriticalPredecessor(eventLog->getFirstEvent());
961

    
962
        for (IEvent *antecessor = eventLog->getFirstEvent(); antecessor; antecessor = antecessor->getNextEvent()) {
963
            if(antecessor==current) {
964
                break; //We have to consider earlier events only
965
            }
966
            if(antecessor->getModuleId() != moduleId && current->getCauseEvent() != antecessor) {
967
                continue; // Check if this is an antecesor
968
            }
969
            if(antecessor->_earliestProcessingTime+current->getComplexity() > current->_earliestProcessingTime) {
970
                current->_earliestProcessingTime = antecessor->_earliestProcessingTime+current->getComplexity();
971
                current->setCriticalPredecessor(antecessor);
972
            }
973
        }
974
        // Memorize max event
975
        if (maxEarliestProcessingTime < current->_earliestProcessingTime) {
976
            maxEarliestProcessingTime = current->_earliestProcessingTime;
977
            maxEarliestProcessingTimeEvent = current;
978
        }
979
    }
980
    //Now produce the convex hull of critical antecessors/predecessors:
981
    cachedCriticalPath.clear();
982
    //Cache largest processing time:
983
    biggestEarliestProcessingTime = maxEarliestProcessingTime / 1000000.0;
984
    biggestEarliestProcessingTimeEvent = maxEarliestProcessingTimeEvent;
985
    for (IEvent *predecessor = maxEarliestProcessingTimeEvent; predecessor ; predecessor = predecessor->getCriticalPredecessor()) {
986
        cachedCriticalPath.insert((ptr_t)predecessor);
987
        if(predecessor->getEventNumber() == 0) {
988
            break;
989
        }
990
    }
991
}
992
/*
993
 * Returns the event with the largest calculated earliest Processing time in REAL_TIME mode
994
 * or the largest endtime in other modes within the given event range.
995
 */
996
ptr_t SequenceChartFacade::getLargestEndtimeInEventRange(ptr_t startEventPtr,
997
        ptr_t endEventPtr, bool duration)
998
{
999
    IEvent *startEvent = (IEvent *) startEventPtr;
1000
    IEvent *endEvent = (IEvent *) endEventPtr;
1001
    switch (timelineMode)
1002
    {
1003
    case REAL_TIME:
1004
    {
1005
        //Use cached result when range contains all events
1006
        if (startEvent == eventLog->getFirstEvent() && endEvent
1007
                == eventLog->getLastEvent())
1008
        {
1009
            return (ptr_t) biggestEarliestProcessingTimeEvent;
1010
        }
1011

    
1012
        long largest = 0;
1013
        IEvent* largestEvent = startEvent;
1014

    
1015
        for (IEvent* current = startEvent; current; current
1016
                = current->getNextEvent())
1017
        {
1018
            long temp = current->getEarliestProcessingTime();
1019
            if (temp > largest)
1020
            {
1021
                largest = temp;
1022
                largestEvent = current;
1023
            }
1024
            if (current == endEvent)
1025
            {
1026
                break;
1027
            }
1028
        }
1029
        return (ptr_t) largestEvent;
1030
    }
1031
    case SIMULATION_TIME:
1032
    case EVENT_NUMBER:
1033
    case STEP:
1034
    case NONLINEAR:
1035
    default:
1036
    {
1037
        if (!duration) {
1038
            return endEventPtr;
1039
        }
1040
        //Use cached result when range contains all events
1041
        if (startEvent == eventLog->getFirstEvent() && endEvent
1042
                == eventLog->getLastEvent() && biggestEndTimeEvent != NULL)
1043
        {
1044
            return (ptr_t) biggestEndTimeEvent;
1045
        }
1046
        simtime_t largest = 0;
1047
        IEvent* largestEvent = endEvent;
1048

    
1049
        for (IEvent* current = endEvent; current; current
1050
                = current->getPreviousEvent())
1051
        {
1052
            simtime_t temp = current->getSimulationTime()
1053
                    + current->getEventEntry()->duration;
1054
            if (temp > largest)
1055
            {
1056
                largest = temp;
1057
                largestEvent = current;
1058
            }
1059
            if (current == startEvent)
1060
            {
1061
                break;
1062
            }
1063
        }
1064
        if (startEvent == eventLog->getFirstEvent() && endEvent
1065
                == eventLog->getLastEvent())
1066
        {
1067
            biggestEndTimeEvent = largestEvent;
1068
        }
1069

    
1070
        return (ptr_t) largestEvent;
1071
    }
1072
    }
1073

    
1074
}
1075