Statistics
| Branch: | Revision:

root / src / eventlog / sequencechartfacade.cc @ 8aeaaccc

History | View | Annotate | Download (38.2 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
    cachedParallelSet.clear();
46
    cachedCriticalPath.clear();
47
}
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
    timelineCoordinateOriginRealTime = 0;
104
}
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
    timelineCoordinateOriginRealTime = event->getEarliestStartTime() / 1000000.0;
114
    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
double SequenceChartFacade::IEvent_getTimelineEventEndCoordinate(ptr_t ptr)
133
{
134
    IEVENT_PTR(ptr);
135
    return getTimelineEventEndCoordinate((IEvent*)ptr);
136
}
137

    
138
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
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
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
            case REAL_TIME:
172
                timelineCoordinate = ((event->getEarliestStartTime()/1000000.0 - timelineCoordinateOriginRealTime));
173
                break;
174
            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
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
            case REAL_TIME:
250
                timelineEventEndCoordinate = (event->getEarliestProcessingTime()/ 1000000.0 - timelineCoordinateOriginRealTime) ;
251
                break;
252
            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
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
        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
                if ((double) current->getEarliestStartTime() / 1000000.0 < timelineCoordinate) {
319
                    if (current->getEarliestStartTime() > res->getEarliestStartTime()) {
320
                        res = current;
321
                    }
322
                }
323
            }
324
            return res;
325
        }
326
        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
        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
                if ((double) current->getEarliestStartTime() / 1000000.0 > timelineCoordinate) {
364
                    if (current->getEarliestStartTime() < res->getEarliestStartTime()) {
365
                        res = current;
366
                    }
367
                }
368
            }
369
            return res;
370
        }
371
        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
        if (timelineMode==REAL_TIME) {
406
            eventSimulationTime = event->getEarliestStartTime() / 1000000.0;
407
        } else {
408
            eventSimulationTime = event->getSimulationTime();
409
        }
410
        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
        else if (timelineMode == REAL_TIME)
420
            eventTimelineCoordinate -= getTimelineCoordinateDelta(0);
421
        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
        if(timelineMode==REAL_TIME) {
430
            nextEventSimulationTime = nextEvent->getEarliestStartTime() / 1000000.0;
431
        } else {
432
            nextEventSimulationTime = nextEvent->getSimulationTime();
433
        }
434

    
435
        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
        case REAL_TIME:
454
        {
455
            simtime_t lastEventSimulationTime = (eventLog->getLastEvent()->getEarliestStartTime())/1000000.0;
456
            //NOTE: This sometimes crashes the Sequencechart because the returned value might be too big
457
            simulationTime = max(BigDecimal::Zero, min(lastEventSimulationTime, (timelineCoordinate + timelineCoordinateOriginRealTime)));
458
        }
459
        break;
460
        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
    if (timelineMode != REAL_TIME)
505
        Assert(simulationTime <= eventLog->getLastEvent()->getSimulationTime());
506

    
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
    if (timelineMode != REAL_TIME)
519
        Assert(simulationTime <= eventLog->getLastEvent()->getSimulationTime());
520

    
521

    
522
    double timelineCoordinate;
523

    
524
    switch (timelineMode)
525
    {
526
        case REAL_TIME:
527
            //treat simulationTime as real time:
528
            timelineCoordinate = simulationTime.dbl() - timelineCoordinateOriginRealTime;
529
            break;
530
        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

    
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
             } else {
721
                 continue;
722
             }
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

    
747
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

    
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
/*
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
/*
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
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
            //The current set does not contain event.
841
            //Therefore the previous set was the largest Parallel Set.
842
            break;
843
        }
844
        prev = prev->getPreviousEvent();
845
    }
846
    return previousSize;
847
}
848
/*
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
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
            //The current set does not contain event.
863
            //Therefore the previous set was the largest Parallel Set.
864
            break;
865
        }
866
        prev = prev->getPreviousEvent();
867
    }
868
    if (prev != event) {
869
        getParallelSet(prev->getNextEvent(), parallelSet);
870
    }
871
    return parallelSet;
872
}
873

    
874
/*
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
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
            if(parallelSet->find((ptr_t)(next->getCauseEvent())) == parallelSet->end()) {
891
                parallelSet->insert((ptr_t) next);
892
            }
893
        }
894
        else
895
        {
896
            break;
897
        }
898
        next = next->getNextEvent();
899
    }
900
}
901
/*
902
 *
903
 */
904
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

    
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
        int moduleId = current->getModuleId();
953
        if(current->getEventEndEntry()) {
954
            current->_earliestProcessingTime = current->getComplexity();
955
        }
956

    
957
        current->setCriticalPredecessor(eventLog->getFirstEvent());
958

    
959
        for (IEvent *antecessor = eventLog->getFirstEvent(); antecessor; antecessor = antecessor->getNextEvent()) {
960
            if(antecessor==current) {
961
                break; //We have to consider earlier events only
962
            }
963
            if(antecessor->getModuleId() != moduleId && current->getCauseEvent() != antecessor) {
964
                continue; // Check if this is an antecesor
965
            }
966
            if(antecessor->_earliestProcessingTime+current->getComplexity() > current->_earliestProcessingTime) {
967
                current->_earliestProcessingTime = antecessor->_earliestProcessingTime+current->getComplexity();
968
                current->setCriticalPredecessor(antecessor);
969
            }
970
        }
971
        // Memorize max event
972
        if (maxEarliestProcessingTime < current->_earliestProcessingTime) {
973
            maxEarliestProcessingTime = current->_earliestProcessingTime;
974
            maxEarliestProcessingTimeEvent = current;
975
        }
976
    }
977
    //Now produce the convex hull of critical antecessors/predecessors:
978
    cachedCriticalPath.clear();
979
    for (IEvent *predecessor = maxEarliestProcessingTimeEvent; predecessor ; predecessor = predecessor->getCriticalPredecessor()) {
980
        cachedCriticalPath.insert((ptr_t)predecessor);
981
        if(predecessor->getEventNumber() == 0) {
982
            break;
983
        }
984
    }
985
}
986

    
987
ptr_t SequenceChartFacade::getLargestEndtimeInEventRange(ptr_t startEventPtr, ptr_t endEventPtr) {
988
    IEvent *startEvent = (IEvent *)startEventPtr;
989
    IEvent *endEvent = (IEvent *)endEventPtr;
990
    switch (timelineMode)
991
    {
992
    case REAL_TIME:
993
    {
994
        long largest = 0;
995
        IEvent* largestEvent = startEvent;
996

    
997
        for (IEvent* current = startEvent; current; current = current->getNextEvent()) {
998
            long temp = current->getEarliestProcessingTime();
999
            if (temp > largest) {
1000
                largest = temp;
1001
                largestEvent = current;
1002
            }
1003
            if (current==endEvent) {
1004
                break;
1005
            }
1006
        }
1007
        return (ptr_t) largestEvent;
1008
    }
1009
    case SIMULATION_TIME:
1010
    case EVENT_NUMBER:
1011
    case STEP:
1012
    case NONLINEAR:
1013
    default:
1014
        return endEventPtr;
1015
    }
1016

    
1017
}