Project

General

Profile

Statistics
| Branch: | Revision:

root / src / eventlog / sequencechartfacade.cc @ 50468190

History | View | Annotate | Download (42.7 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
    maximumOverlapping = -1;
46

    
47
    biggestEarliestProcessingTime = 0;
48

    
49
    biggestEndTimeEvent = NULL;
50

    
51
    cachedParallelSet.clear();
52
    cachedCriticalPath.clear();
53
}
54

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

    
60
        setNonLinearFocus(calculateNonLinearFocus());
61

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

    
65
            if (event)
66
                relocateTimelineCoordinateSystem(event);
67
            else
68
                undefineTimelineCoordinateSystem();
69
        }
70
    }
71
}
72

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

    
80
        if (totalSimulationTimeDelta == 0)
81
            totalSimulationTimeDelta = firstEventSimulationTime;
82

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

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

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

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

    
112
void SequenceChartFacade::relocateTimelineCoordinateSystem(IEvent *event)
113
{
114
    Assert(event);
115

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

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

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

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

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

    
144
double SequenceChartFacade::getTimelineCoordinateDelta(double simulationTimeDelta)
145
{
146
    Assert(nonLinearFocus > 0);
147

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

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

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

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

    
173
    if (this->timelineCoordinateSystemVersion > event->cachedTimelineCoordinateSystemVersion) {
174
        double timelineCoordinate;
175

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

    
194
                    Assert(event->getEventNumber() < timelineCoordinateRangeStartEventNumber || timelineCoordinateRangeEndEventNumber < event->getEventNumber());
195

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

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

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

    
211
                        if (forward) {
212
                            timelineCoordinate = previousTimelineCoordinate + timelineCoordinateDelta;
213

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

    
220
                            if (timelineCoordinate < lowerTimelineCoordinateCalculationLimit)
221
                                return NaN;
222
                        }
223

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

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

    
239
        event->cachedTimelineCoordinate = timelineCoordinate;
240
        event->cachedTimelineCoordinateSystemVersion = timelineCoordinateSystemVersion;
241
    }
242

    
243
    return event->cachedTimelineCoordinate;
244
}
245

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

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

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

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

    
286
    Assert(timelineCoordinateRangeStartEvent && timelineCoordinateRangeEndEvent);
287

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

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

    
310
    return currentEvent;
311
}
312

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

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

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

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

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

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

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

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

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

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

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

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

    
441
        nextEventTimelineCoordinate = getTimelineCoordinate(nextEvent);
442

    
443
        simulationTimeDelta = nextEventSimulationTime - eventSimulationTime;
444
        timelineCoordinateDelta = nextEventTimelineCoordinate - eventTimelineCoordinate;
445
    }
446
}
447

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

    
452
    if (eventLog->isEmpty())
453
        return BigDecimal::Zero;
454

    
455
    simtime_t simulationTime;
456

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

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

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

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

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

    
519
    if (eventLog->isEmpty())
520
        return 0;
521

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

    
527
    double timelineCoordinate;
528

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

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

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

    
574
    Assert(!isNaN(timelineCoordinate));
575

    
576
    return timelineCoordinate;
577
}
578

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

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

    
587
        event = event->getNextEvent();
588
    }
589

    
590
    return getTimelineCoordinateForSimulationTime(simulationTime);
591
}
592

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

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

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

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

    
611
        if (event == endEvent)
612
            break;
613
    }
614

    
615
    return moduleMethodBeginEntries;
616
}
617

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

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

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

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

    
641
        IMessageDependencyList *consequences = event->getConsequences();
642

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

    
646
        if (event == endEvent)
647
            break;
648
    }
649

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

    
654
    return result;
655
}
656

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

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

    
667
    int numberOfAxes = axisIndexSet.size();
668
    adjacencyMatrix.resize(numberOfAxes * numberOfAxes);
669

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

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

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

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

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

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

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

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

    
715
    return adjacencyMatrix;
716
}
717

    
718

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

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

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

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

    
785

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

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

    
808
/*
809
 * Returns whether an event not part of a set of parallel events with more than treshold elements.
810
 */
811
bool SequenceChartFacade::isBottleneck(IEvent* event, double threshold)
812
{
813
    if (isOnCriticalPath(event)) {
814
        return getOverlappingQuotient((ptr_t)event) <= threshold;
815
    }
816
    return false;
817
}
818
/*
819
 * Returns whether event is in the largest parallel set of selected.
820
 */
821
bool SequenceChartFacade::isParallelWithEvent(IEvent* event, IEvent* selected) {
822

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

    
844
        getParallelSet(prev, &parallelSet);
845

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

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

    
941
/*
942
 * Determines whether the event lies on the critical path
943
 */
944
bool SequenceChartFacade::isOnCriticalPath(IEvent* event) {
945
    if (cachedCriticalPath.empty()) {
946
        calculateCriticalPath();
947
    }
948
    return (cachedCriticalPath.find((ptr_t)event) != cachedCriticalPath.end());
949
}
950

    
951
/*
952
 * Calculates the critical path of the run and stores it in the set cachedCriticalPath
953
 */
954
void SequenceChartFacade::calculateCriticalPath() {
955
    long maxEarliestProcessingTime = 0;
956
    IEvent* maxEarliestProcessingTimeEvent;
957

    
958
    for (IEvent *current = eventLog->getFirstEvent(); current; current = current->getNextEvent()) {
959
        simtime_t startTime = current->getSimulationTime();
960
        int moduleId = current->getModuleId();
961
        if(current->getEventEndEntry()) {
962
            current->_earliestProcessingTime = current->getComplexity();
963
        }
964

    
965
        current->setCriticalPredecessor(eventLog->getFirstEvent());
966

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

    
1017
        long largest = 0;
1018
        IEvent* largestEvent = startEvent;
1019

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

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

    
1075
        return (ptr_t) largestEvent;
1076
    }
1077
    }
1078

    
1079
}
1080

    
1081
double SequenceChartFacade::getOverlapping(ptr_t eventPtr) {
1082
    long overlapping = 0;
1083
    IEvent* event = (IEvent*) eventPtr;
1084

    
1085
    long eventProcessingTime = event->getEarliestProcessingTime();
1086
    long eventStartTime = event->getEarliestStartTime();
1087

    
1088
    for (IEvent *current = eventLog->getFirstEvent(); current; current = current->getNextEvent()) {
1089

    
1090
        if(current->getComplexity() == 0) {
1091
            continue;
1092
        }
1093

    
1094
        long currentStartTime = current->getEarliestStartTime();
1095
        long currentProcessingTime = current->getEarliestProcessingTime();
1096

    
1097
        if(eventStartTime <= currentStartTime && eventProcessingTime >= currentStartTime) {
1098
            overlapping += eventProcessingTime - currentStartTime;
1099
        } else if (currentStartTime <= eventStartTime && currentProcessingTime >= eventStartTime) {
1100
            overlapping += currentProcessingTime - eventStartTime;
1101
        } else if (currentStartTime <= eventStartTime && currentProcessingTime >= eventProcessingTime) {
1102
            overlapping += event->getComplexity();
1103
        }
1104
    }
1105
    return overlapping / (event->getComplexity() * 1.0);
1106
}
1107

    
1108
double SequenceChartFacade::getMaximumOverlapping() {
1109
    double maxOverlapping = 0;
1110
    for (IEvent *current = eventLog->getFirstEvent(); current; current = current->getNextEvent()) {
1111
        if(!isOnCriticalPath(current) || current->getComplexity() == 0) {
1112
            continue;
1113
        }
1114
        double overlapping = getOverlapping((ptr_t) current);
1115
        if (overlapping > maxOverlapping){
1116
            maxOverlapping = overlapping;
1117
        }
1118
    }
1119
    return maxOverlapping;
1120
}
1121

    
1122
/*
1123
 * returns the quotient of
1124
 * relative overlapping cputime with the event / maximum relative overlapping
1125
 * cputime with any event of the critical path
1126
 */
1127
double SequenceChartFacade::getOverlappingQuotient(ptr_t eventPtr) {
1128

    
1129
    if (((IEvent*)eventPtr)->getComplexity() == 0) {
1130
        return 0;
1131
    }
1132
    double overlapping = getOverlapping(eventPtr);
1133

    
1134
    if (maximumOverlapping == -1) {
1135
        maximumOverlapping = getMaximumOverlapping();
1136
    }
1137

    
1138
    return overlapping / maximumOverlapping;
1139
}
1140

    
1141
bool SequenceChartFacade::isOverlappingInRealTimeDomain(ptr_t eventPtr1, ptr_t eventPtr2) {
1142
    long eventProcessingTime1 = ((IEvent*)eventPtr1)->getEarliestProcessingTime();
1143
    long eventStartTime1 = ((IEvent*)eventPtr1)->getEarliestStartTime();
1144
    long eventProcessingTime2 = ((IEvent*)eventPtr2)->getEarliestProcessingTime();
1145
    long eventStartTime2 = ((IEvent*)eventPtr2)->getEarliestStartTime();
1146

    
1147
    return !(eventProcessingTime1 < eventStartTime2 || eventProcessingTime2 < eventStartTime1);
1148
}